| 1 | greg | 2.7 | /* RCSid $Id: bsdf.h,v 2.6 2011/02/19 01:48:59 greg Exp $ */ | 
| 2 | greg | 2.4 | /* | 
| 3 |  |  | *  bsdf.h | 
| 4 |  |  | * | 
| 5 |  |  | *  Declarations for bidirectional scattering distribution functions. | 
| 6 |  |  | *  Assumes <stdio.h> already included. | 
| 7 |  |  | * | 
| 8 |  |  | *  A material is oriented in right-hand coordinate system with X-axis | 
| 9 |  |  | *      in the surface plane pointed to the right as seen from the front. | 
| 10 |  |  | *      This means the Y-axis is "up" and the Z-axis is the surface normal. | 
| 11 |  |  | * | 
| 12 |  |  | *  BSDF vectors always oriented away from surface, even when "incident." | 
| 13 |  |  | * | 
| 14 |  |  | *  Created by Greg Ward on 1/10/11. | 
| 15 |  |  | * | 
| 16 |  |  | */ | 
| 17 |  |  |  | 
| 18 |  |  | #ifndef _BSDF_H_ | 
| 19 |  |  | #define _BSDF_H_ | 
| 20 |  |  |  | 
| 21 |  |  | #include "fvect.h" | 
| 22 |  |  | #include "ccolor.h" | 
| 23 |  |  |  | 
| 24 |  |  | #ifdef __cplusplus | 
| 25 |  |  | extern "C" { | 
| 26 |  |  | #endif | 
| 27 |  |  |  | 
| 28 |  |  | #define SDnameLn        128             /* maximum BSDF name length */ | 
| 29 |  |  | #define SDmaxCh         3               /* maximum # spectral channels */ | 
| 30 |  |  |  | 
| 31 |  |  | /* Component flags for SDsampBSDF() and SDhemiScatter() */ | 
| 32 |  |  | #define SDsampR         0x1             /* include reflection */ | 
| 33 |  |  | #define SDsampT         0x2             /* include transmission */ | 
| 34 |  |  | #define SDsampS         0x3             /* include scattering (R+T) */ | 
| 35 |  |  | #define SDsampSp        0x4             /* include non-diffuse portion */ | 
| 36 |  |  | #define SDsampDf        0x8             /* include diffuse portion */ | 
| 37 |  |  | #define SDsampSpR       0x5             /* include non-diffuse reflection */ | 
| 38 |  |  | #define SDsampSpT       0x6             /* include non-diffuse transmission */ | 
| 39 |  |  | #define SDsampSpS       0x7             /* include non-diffuse scattering */ | 
| 40 |  |  | #define SDsampAll       0xF             /* include everything */ | 
| 41 |  |  |  | 
| 42 |  |  | /* Projected solid angle query flags fos SDsizeBSDF() */ | 
| 43 | greg | 2.7 | #define SDqueryVal      0x0             /* query single value */ | 
| 44 |  |  | #define SDqueryMin      0x1             /* query minimum proj. solid angle */ | 
| 45 |  |  | #define SDqueryMax      0x2             /* query maximum proj. solid angle */ | 
| 46 | greg | 2.4 |  | 
| 47 |  |  | /* Error codes: normal return, out of memory, file i/o, file format, bad argument, | 
| 48 |  |  | bad data, unsupported feature, internal error, unknown error */ | 
| 49 |  |  | typedef enum {SDEnone=0, SDEmemory, SDEfile, SDEformat, SDEargument, | 
| 50 |  |  | SDEdata, SDEsupport, SDEinternal, SDEunknown} SDError; | 
| 51 |  |  |  | 
| 52 |  |  | /* English ASCII strings corresponding to ennumerated errors */ | 
| 53 |  |  | extern const char       *SDerrorEnglish[]; | 
| 54 |  |  |  | 
| 55 |  |  | /* Additional information on last error (ASCII English) */ | 
| 56 |  |  | extern char             SDerrorDetail[]; | 
| 57 |  |  |  | 
| 58 |  |  | /* Holder for BSDF value and spectral color */ | 
| 59 |  |  | typedef struct { | 
| 60 |  |  | double          cieY;           /* photopic BSDF (Y) value */ | 
| 61 |  |  | C_COLOR         spec;           /* spectral and (x,y) color */ | 
| 62 |  |  | } SDValue; | 
| 63 |  |  |  | 
| 64 |  |  | /* Cached, encoded, cumulative distribution for one incident (solid) angle */ | 
| 65 |  |  | #define SD_CDIST_BASE   double          cTotal; \ | 
| 66 |  |  | struct SDCDst_s *next | 
| 67 |  |  | typedef struct SDCDst_s { | 
| 68 |  |  | SD_CDIST_BASE;                  /* base fields first */ | 
| 69 |  |  | /* ...encoded distribution extends struct */ | 
| 70 |  |  | } SDCDst; | 
| 71 |  |  |  | 
| 72 |  |  | /* Forward declaration of BSDF component */ | 
| 73 |  |  | typedef struct SDComp_s SDComponent; | 
| 74 |  |  |  | 
| 75 |  |  | /* Methods needed to handle BSDF components (nothing is optional) */ | 
| 76 |  |  | typedef const struct { | 
| 77 |  |  | /* return non-diffuse BSDF */ | 
| 78 |  |  | int             (*getBSDFs)(float coef[SDmaxCh], const FVECT outVec, | 
| 79 |  |  | const FVECT inVec, const void *dist); | 
| 80 |  |  | /* query non-diffuse PSA for vector */ | 
| 81 |  |  | SDError         (*queryProjSA)(double *psa, const FVECT vec, | 
| 82 |  |  | int qflags, const void *dist); | 
| 83 |  |  | /* get cumulative distribution */ | 
| 84 |  |  | const SDCDst    *(*getCDist)(const FVECT inVec, SDComponent *sdc); | 
| 85 |  |  | /* sample cumulative distribution */ | 
| 86 |  |  | SDError         (*sampCDist)(FVECT outVec, double randX, | 
| 87 |  |  | const SDCDst *cdp); | 
| 88 |  |  | /* free a spectral BSDF component */ | 
| 89 |  |  | void            (*freeSC)(void *dist); | 
| 90 |  |  | } SDFunc; | 
| 91 |  |  |  | 
| 92 |  |  | /* Structure to hold a spectral BSDF component (typedef SDComponent above) */ | 
| 93 |  |  | struct SDComp_s { | 
| 94 |  |  | C_COLOR         cspec[SDmaxCh]; /* component spectral bases */ | 
| 95 |  |  | SDFunc          *func;          /* methods for this component */ | 
| 96 |  |  | void            *dist;          /* loaded distribution data */ | 
| 97 |  |  | SDCDst          *cdList;        /* cumulative distribution cache */ | 
| 98 |  |  | }; | 
| 99 |  |  |  | 
| 100 |  |  | /* Container for non-diffuse BSDF components */ | 
| 101 |  |  | typedef struct { | 
| 102 |  |  | double          minProjSA;      /* minimum projected solid angle */ | 
| 103 |  |  | double          maxHemi;        /* maximum directional hemispherical */ | 
| 104 |  |  | int             ncomp;          /* number of separate components */ | 
| 105 |  |  | SDComponent     comp[1];        /* BSDF components (extends struct) */ | 
| 106 |  |  | } SDSpectralDF; | 
| 107 |  |  |  | 
| 108 |  |  | /* Loaded BSDF data */ | 
| 109 |  |  | typedef struct { | 
| 110 |  |  | char            name[SDnameLn]; /* BSDF name (derived from file) */ | 
| 111 |  |  | char            *mgf;           /* geometric description (if any) */ | 
| 112 |  |  | float           dim[3];         /* width, height, thickness (meters) */ | 
| 113 |  |  | SDValue         rLambFront;     /* diffuse front reflectance */ | 
| 114 |  |  | SDValue         rLambBack;      /* diffuse rear reflectance */ | 
| 115 |  |  | SDValue         tLamb;          /* diffuse transmission */ | 
| 116 |  |  | SDSpectralDF    *rf, *rb, *tf;  /* non-diffuse BSDF components */ | 
| 117 |  |  | } SDData; | 
| 118 |  |  |  | 
| 119 |  |  | /* List of loaded BSDFs */ | 
| 120 |  |  | extern struct SDCache_s { | 
| 121 |  |  | SDData          bsdf;           /* BSDF data */ | 
| 122 |  |  | unsigned        refcnt;         /* how many callers are using us? */ | 
| 123 |  |  | struct SDCache_s                /* next in cache list */ | 
| 124 |  |  | *next; | 
| 125 |  |  | } *SDcacheList;         /* Global BSDF cache */ | 
| 126 |  |  |  | 
| 127 |  |  | /* BSDF cache retention preference */ | 
| 128 |  |  | #define SDretainNone    0               /* free unreferenced data (default) */ | 
| 129 |  |  | #define SDretainBSDFs   1               /* keep loaded BSDFs in cache */ | 
| 130 |  |  | #define SDretainAll     2               /* also keep cumulative cache data */ | 
| 131 |  |  |  | 
| 132 |  |  | extern int              SDretainSet;    /* set to SDretainNone by default */ | 
| 133 |  |  |  | 
| 134 |  |  | /***************************************************************** | 
| 135 |  |  | * The following routines are less commonly used by applications. | 
| 136 |  |  | */ | 
| 137 |  |  |  | 
| 138 | greg | 2.6 | #define SDisLoaded(sd)  ((sd)->rLambFront.spec.flags != 0) | 
| 139 | greg | 2.4 |  | 
| 140 |  |  | /* Report an error to the indicated stream (in English) */ | 
| 141 |  |  | extern SDError          SDreportEnglish(SDError ec, FILE *fp); | 
| 142 |  |  |  | 
| 143 |  |  | /* Shorten file path to useable BSDF name, removing suffix */ | 
| 144 |  |  | extern void             SDclipName(char res[SDnameLn], const char *fname); | 
| 145 |  |  |  | 
| 146 |  |  | /* Allocate new spectral distribution function */ | 
| 147 |  |  | extern SDSpectralDF     *SDnewSpectralDF(int nc); | 
| 148 |  |  |  | 
| 149 |  |  | /* Free a spectral distribution function */ | 
| 150 |  |  | extern void             SDfreeSpectralDF(SDSpectralDF *df); | 
| 151 |  |  |  | 
| 152 |  |  | /* Initialize an unused BSDF struct (clears to zeroes) */ | 
| 153 |  |  | extern void             SDclearBSDF(SDData *sd); | 
| 154 |  |  |  | 
| 155 |  |  | /* Load a BSDF struct from the given file (keeps name unchanged) */ | 
| 156 |  |  | extern SDError          SDloadFile(SDData *sd, const char *fname); | 
| 157 |  |  |  | 
| 158 |  |  | /* Free data associated with BSDF struct */ | 
| 159 |  |  | extern void             SDfreeBSDF(SDData *sd); | 
| 160 |  |  |  | 
| 161 |  |  | /* Find writeable BSDF by name, or allocate new cache entry if absent */ | 
| 162 |  |  | extern SDData           *SDgetCache(const char *bname); | 
| 163 |  |  |  | 
| 164 |  |  | /* Free cached cumulative distributions for BSDF component */ | 
| 165 |  |  | extern void             SDfreeCumulativeCache(SDSpectralDF *df); | 
| 166 |  |  |  | 
| 167 |  |  | /* Sample an individual BSDF component */ | 
| 168 |  |  | extern SDError          SDsampComponent(SDValue *sv, FVECT outVec, | 
| 169 |  |  | const FVECT inVec, double randX, | 
| 170 |  |  | SDComponent *sdc); | 
| 171 |  |  |  | 
| 172 |  |  | /* Convert 1-dimensional random variable to N-dimensional */ | 
| 173 |  |  | extern void             SDmultiSamp(double t[], int n, double randX); | 
| 174 |  |  |  | 
| 175 |  |  | /* Map a [0,1]^2 square to a unit radius disk */ | 
| 176 |  |  | void                    SDsquare2disk(double ds[2], double seedx, double seedy); | 
| 177 |  |  |  | 
| 178 |  |  | /* Map point on unit disk to a unit square in [0,1]^2 range */ | 
| 179 |  |  | void                    SDdisk2square(double sq[2], double diskx, double disky); | 
| 180 |  |  |  | 
| 181 |  |  | /***************************************************************** | 
| 182 |  |  | * The calls below are the ones most applications require. | 
| 183 |  |  | * All directions are assumed to be unit vectors. | 
| 184 |  |  | */ | 
| 185 |  |  |  | 
| 186 |  |  | /* Get BSDF from cache (or load and cache it on first call) */ | 
| 187 |  |  | /* Report any problems to stderr and return NULL on failure */ | 
| 188 |  |  | extern const SDData     *SDcacheFile(const char *fname); | 
| 189 |  |  |  | 
| 190 |  |  | /* Free a BSDF from our cache (clear all if NULL) */ | 
| 191 |  |  | extern void             SDfreeCache(const SDData *sd); | 
| 192 |  |  |  | 
| 193 |  |  | /* Query projected solid angle resolution for non-diffuse BSDF direction */ | 
| 194 |  |  | extern SDError          SDsizeBSDF(double *projSA, const FVECT vec, | 
| 195 |  |  | int qflags, const SDData *sd); | 
| 196 |  |  |  | 
| 197 |  |  | /* Return BSDF for the given incident and scattered ray vectors */ | 
| 198 |  |  | extern SDError          SDevalBSDF(SDValue *sv, const FVECT outVec, | 
| 199 |  |  | const FVECT inVec, const SDData *sd); | 
| 200 |  |  |  | 
| 201 |  |  | /* Compute directional hemispherical scattering at given incident angle */ | 
| 202 |  |  | extern double           SDdirectHemi(const FVECT inVec, | 
| 203 |  |  | int sflags, const SDData *sd); | 
| 204 |  |  |  | 
| 205 |  |  | /* Sample BSDF direction based on the given random variable */ | 
| 206 |  |  | extern SDError          SDsampBSDF(SDValue *sv, FVECT outVec, | 
| 207 |  |  | const FVECT inVec, double randX, | 
| 208 |  |  | int sflags, const SDData *sd); | 
| 209 |  |  |  | 
| 210 |  |  | /***************************************************************** | 
| 211 |  |  | * Vector math for getting between world and local BSDF coordinates. | 
| 212 |  |  | * Directions may be passed unnormalized to these routines. | 
| 213 |  |  | */ | 
| 214 |  |  |  | 
| 215 |  |  | /* Compute World->BSDF transform from surface normal and up (Y) vector */ | 
| 216 |  |  | extern SDError          SDcompXform(RREAL vMtx[3][3], const FVECT sNrm, | 
| 217 |  |  | const FVECT uVec); | 
| 218 |  |  |  | 
| 219 |  |  | /* Compute inverse transform */ | 
| 220 |  |  | extern SDError          SDinvXform(RREAL iMtx[3][3], RREAL vMtx[3][3]); | 
| 221 |  |  |  | 
| 222 |  |  | /* Transform and normalize direction (column) vector */ | 
| 223 |  |  | extern SDError          SDmapDir(FVECT resVec, RREAL vMtx[3][3], | 
| 224 |  |  | const FVECT inpVec); | 
| 225 |  |  |  | 
| 226 | greg | 2.5 | /* System-specific BSDF loading routine (not part of our library) */ | 
| 227 |  |  | extern SDData           *loadBSDF(char *name); | 
| 228 |  |  |  | 
| 229 |  |  | /* System-specific BSDF error translator (not part of our library) */ | 
| 230 |  |  | extern char             *transSDError(SDError ec); | 
| 231 |  |  |  | 
| 232 | greg | 2.4 | /*################################################################*/ | 
| 233 |  |  | /*######### DEPRECATED DEFINITIONS AWAITING PERMANENT REMOVAL #######*/ | 
| 234 | greg | 2.1 | /* | 
| 235 |  |  | * Header for BSDF i/o and access routines | 
| 236 |  |  | */ | 
| 237 | greg | 2.2 |  | 
| 238 | greg | 2.4 | #include "mat4.h" | 
| 239 | greg | 2.1 | /* up directions */ | 
| 240 |  |  | typedef enum { | 
| 241 |  |  | UDzneg=-3, | 
| 242 |  |  | UDyneg=-2, | 
| 243 |  |  | UDxneg=-1, | 
| 244 |  |  | UDunknown=0, | 
| 245 |  |  | UDxpos=1, | 
| 246 |  |  | UDypos=2, | 
| 247 |  |  | UDzpos=3 | 
| 248 |  |  | } UpDir; | 
| 249 |  |  | /* BSDF coordinate calculation routines */ | 
| 250 |  |  | /* vectors always point away from surface */ | 
| 251 | greg | 2.4 |  | 
| 252 |  |  | typedef int     b_vecf2(FVECT v, int n, void *cd); | 
| 253 |  |  | typedef int     b_ndxf2(FVECT v, void *cd); | 
| 254 |  |  | typedef double  b_radf2(int n, void *cd); | 
| 255 | greg | 2.1 |  | 
| 256 |  |  | /* Bidirectional Scattering Distribution Function */ | 
| 257 |  |  | struct BSDF_data { | 
| 258 |  |  | int     ninc;                   /* number of incoming directions */ | 
| 259 |  |  | int     nout;                   /* number of outgoing directions */ | 
| 260 | greg | 2.3 | float   dim[3];                 /* width, height, thickness (meters) */ | 
| 261 |  |  | char    *mgf;                   /* geometric description (if any) */ | 
| 262 | greg | 2.1 | void    *ib_priv;               /* input basis private data */ | 
| 263 | greg | 2.4 | b_vecf2 *ib_vec;                /* get input vector from index */ | 
| 264 |  |  | b_ndxf2 *ib_ndx;                /* get input index from vector */ | 
| 265 |  |  | b_radf2 *ib_ohm;                /* get input radius for index */ | 
| 266 | greg | 2.1 | void    *ob_priv;               /* output basis private data */ | 
| 267 | greg | 2.4 | b_vecf2 *ob_vec;                /* get output vector from index */ | 
| 268 |  |  | b_ndxf2 *ob_ndx;                /* get output index from vector */ | 
| 269 |  |  | b_radf2 *ob_ohm;                /* get output radius for index */ | 
| 270 | greg | 2.1 | float   *bsdf;                  /* scattering distribution data */ | 
| 271 |  |  | };                              /* bidirectional scattering distrib. func. */ | 
| 272 |  |  |  | 
| 273 |  |  | #define getBSDF_incvec(v,b,i)   (*(b)->ib_vec)(v,i,(b)->ib_priv) | 
| 274 |  |  | #define getBSDF_incndx(b,v)     (*(b)->ib_ndx)(v,(b)->ib_priv) | 
| 275 |  |  | #define getBSDF_incohm(b,i)     (*(b)->ib_ohm)(i,(b)->ib_priv) | 
| 276 |  |  | #define getBSDF_outvec(v,b,o)   (*(b)->ob_vec)(v,o,(b)->ob_priv) | 
| 277 |  |  | #define getBSDF_outndx(b,v)     (*(b)->ob_ndx)(v,(b)->ob_priv) | 
| 278 |  |  | #define getBSDF_outohm(b,o)     (*(b)->ob_ohm)(o,(b)->ob_priv) | 
| 279 |  |  | #define BSDF_value(b,i,o)       (b)->bsdf[(o)*(b)->ninc + (i)] | 
| 280 |  |  |  | 
| 281 |  |  | extern struct BSDF_data *load_BSDF(char *fname); | 
| 282 |  |  | extern void free_BSDF(struct BSDF_data *b); | 
| 283 |  |  | extern int r_BSDF_incvec(FVECT v, struct BSDF_data *b, int i, | 
| 284 |  |  | double rv, MAT4 xm); | 
| 285 |  |  | extern int r_BSDF_outvec(FVECT v, struct BSDF_data *b, int o, | 
| 286 |  |  | double rv, MAT4 xm); | 
| 287 | greg | 2.3 | extern int getBSDF_xfm(MAT4 xm, FVECT nrm, UpDir ud, char *xfbuf); | 
| 288 | greg | 2.2 |  | 
| 289 | greg | 2.4 | /*######### END DEPRECATED DEFINITIONS #######*/ | 
| 290 |  |  | /*################################################################*/ | 
| 291 |  |  |  | 
| 292 |  |  | #ifdef __cplusplus | 
| 293 |  |  | } | 
| 294 |  |  | #endif | 
| 295 |  |  | #endif  /* ! _BSDF_H_ */ |