--- ray/src/common/bsdf.h 2010/09/03 23:53:50 2.3 +++ ray/src/common/bsdf.h 2011/02/18 00:40:25 2.4 @@ -1,10 +1,236 @@ -/* RCSid $Id: bsdf.h,v 2.3 2010/09/03 23:53:50 greg Exp $ */ +/* RCSid $Id: bsdf.h,v 2.4 2011/02/18 00:40:25 greg Exp $ */ /* + * bsdf.h + * + * Declarations for bidirectional scattering distribution functions. + * Assumes already included. + * + * A material is oriented in right-hand coordinate system with X-axis + * in the surface plane pointed to the right as seen from the front. + * This means the Y-axis is "up" and the Z-axis is the surface normal. + * + * BSDF vectors always oriented away from surface, even when "incident." + * + * Created by Greg Ward on 1/10/11. + * + */ + +#ifndef _BSDF_H_ +#define _BSDF_H_ + +#include "fvect.h" +#include "ccolor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SDnameLn 128 /* maximum BSDF name length */ +#define SDmaxCh 3 /* maximum # spectral channels */ + +/* Component flags for SDsampBSDF() and SDhemiScatter() */ +#define SDsampR 0x1 /* include reflection */ +#define SDsampT 0x2 /* include transmission */ +#define SDsampS 0x3 /* include scattering (R+T) */ +#define SDsampSp 0x4 /* include non-diffuse portion */ +#define SDsampDf 0x8 /* include diffuse portion */ +#define SDsampSpR 0x5 /* include non-diffuse reflection */ +#define SDsampSpT 0x6 /* include non-diffuse transmission */ +#define SDsampSpS 0x7 /* include non-diffuse scattering */ +#define SDsampAll 0xF /* include everything */ + +/* Projected solid angle query flags fos SDsizeBSDF() */ +#define SDqueryInc 0x1 /* query incoming vector */ +#define SDqueryOut 0x2 /* query outgoing vector */ +#define SDqueryMin 0x4 /* query minimum proj. solid angle */ +#define SDqueryMax 0x8 /* query maximum proj. solid angle */ + +/* Error codes: normal return, out of memory, file i/o, file format, bad argument, + bad data, unsupported feature, internal error, unknown error */ +typedef enum {SDEnone=0, SDEmemory, SDEfile, SDEformat, SDEargument, + SDEdata, SDEsupport, SDEinternal, SDEunknown} SDError; + +/* English ASCII strings corresponding to ennumerated errors */ +extern const char *SDerrorEnglish[]; + +/* Additional information on last error (ASCII English) */ +extern char SDerrorDetail[]; + +/* Holder for BSDF value and spectral color */ +typedef struct { + double cieY; /* photopic BSDF (Y) value */ + C_COLOR spec; /* spectral and (x,y) color */ +} SDValue; + +/* Cached, encoded, cumulative distribution for one incident (solid) angle */ +#define SD_CDIST_BASE double cTotal; \ + struct SDCDst_s *next +typedef struct SDCDst_s { + SD_CDIST_BASE; /* base fields first */ + /* ...encoded distribution extends struct */ +} SDCDst; + +/* Forward declaration of BSDF component */ +typedef struct SDComp_s SDComponent; + +/* Methods needed to handle BSDF components (nothing is optional) */ +typedef const struct { + /* return non-diffuse BSDF */ + int (*getBSDFs)(float coef[SDmaxCh], const FVECT outVec, + const FVECT inVec, const void *dist); + /* query non-diffuse PSA for vector */ + SDError (*queryProjSA)(double *psa, const FVECT vec, + int qflags, const void *dist); + /* get cumulative distribution */ + const SDCDst *(*getCDist)(const FVECT inVec, SDComponent *sdc); + /* sample cumulative distribution */ + SDError (*sampCDist)(FVECT outVec, double randX, + const SDCDst *cdp); + /* free a spectral BSDF component */ + void (*freeSC)(void *dist); +} SDFunc; + +/* Structure to hold a spectral BSDF component (typedef SDComponent above) */ +struct SDComp_s { + C_COLOR cspec[SDmaxCh]; /* component spectral bases */ + SDFunc *func; /* methods for this component */ + void *dist; /* loaded distribution data */ + SDCDst *cdList; /* cumulative distribution cache */ +}; + +/* Container for non-diffuse BSDF components */ +typedef struct { + double minProjSA; /* minimum projected solid angle */ + double maxHemi; /* maximum directional hemispherical */ + int ncomp; /* number of separate components */ + SDComponent comp[1]; /* BSDF components (extends struct) */ +} SDSpectralDF; + +/* Loaded BSDF data */ +typedef struct { + char name[SDnameLn]; /* BSDF name (derived from file) */ + char *mgf; /* geometric description (if any) */ + float dim[3]; /* width, height, thickness (meters) */ + SDValue rLambFront; /* diffuse front reflectance */ + SDValue rLambBack; /* diffuse rear reflectance */ + SDValue tLamb; /* diffuse transmission */ + SDSpectralDF *rf, *rb, *tf; /* non-diffuse BSDF components */ +} SDData; + +/* List of loaded BSDFs */ +extern struct SDCache_s { + SDData bsdf; /* BSDF data */ + unsigned refcnt; /* how many callers are using us? */ + struct SDCache_s /* next in cache list */ + *next; +} *SDcacheList; /* Global BSDF cache */ + +/* BSDF cache retention preference */ +#define SDretainNone 0 /* free unreferenced data (default) */ +#define SDretainBSDFs 1 /* keep loaded BSDFs in cache */ +#define SDretainAll 2 /* also keep cumulative cache data */ + +extern int SDretainSet; /* set to SDretainNone by default */ + +/***************************************************************** + * The following routines are less commonly used by applications. + */ + +#define SDisLoaded(sd) ((sd)->rLambFront.spec.clock != 0) + +/* Report an error to the indicated stream (in English) */ +extern SDError SDreportEnglish(SDError ec, FILE *fp); + +/* Shorten file path to useable BSDF name, removing suffix */ +extern void SDclipName(char res[SDnameLn], const char *fname); + +/* Allocate new spectral distribution function */ +extern SDSpectralDF *SDnewSpectralDF(int nc); + +/* Free a spectral distribution function */ +extern void SDfreeSpectralDF(SDSpectralDF *df); + +/* Initialize an unused BSDF struct (clears to zeroes) */ +extern void SDclearBSDF(SDData *sd); + +/* Load a BSDF struct from the given file (keeps name unchanged) */ +extern SDError SDloadFile(SDData *sd, const char *fname); + +/* Free data associated with BSDF struct */ +extern void SDfreeBSDF(SDData *sd); + +/* Find writeable BSDF by name, or allocate new cache entry if absent */ +extern SDData *SDgetCache(const char *bname); + +/* Free cached cumulative distributions for BSDF component */ +extern void SDfreeCumulativeCache(SDSpectralDF *df); + +/* Sample an individual BSDF component */ +extern SDError SDsampComponent(SDValue *sv, FVECT outVec, + const FVECT inVec, double randX, + SDComponent *sdc); + +/* Convert 1-dimensional random variable to N-dimensional */ +extern void SDmultiSamp(double t[], int n, double randX); + +/* Map a [0,1]^2 square to a unit radius disk */ +void SDsquare2disk(double ds[2], double seedx, double seedy); + +/* Map point on unit disk to a unit square in [0,1]^2 range */ +void SDdisk2square(double sq[2], double diskx, double disky); + +/***************************************************************** + * The calls below are the ones most applications require. + * All directions are assumed to be unit vectors. + */ + +/* Get BSDF from cache (or load and cache it on first call) */ +/* Report any problems to stderr and return NULL on failure */ +extern const SDData *SDcacheFile(const char *fname); + +/* Free a BSDF from our cache (clear all if NULL) */ +extern void SDfreeCache(const SDData *sd); + +/* Query projected solid angle resolution for non-diffuse BSDF direction */ +extern SDError SDsizeBSDF(double *projSA, const FVECT vec, + int qflags, const SDData *sd); + +/* Return BSDF for the given incident and scattered ray vectors */ +extern SDError SDevalBSDF(SDValue *sv, const FVECT outVec, + const FVECT inVec, const SDData *sd); + +/* Compute directional hemispherical scattering at given incident angle */ +extern double SDdirectHemi(const FVECT inVec, + int sflags, const SDData *sd); + +/* Sample BSDF direction based on the given random variable */ +extern SDError SDsampBSDF(SDValue *sv, FVECT outVec, + const FVECT inVec, double randX, + int sflags, const SDData *sd); + +/***************************************************************** + * Vector math for getting between world and local BSDF coordinates. + * Directions may be passed unnormalized to these routines. + */ + +/* Compute World->BSDF transform from surface normal and up (Y) vector */ +extern SDError SDcompXform(RREAL vMtx[3][3], const FVECT sNrm, + const FVECT uVec); + +/* Compute inverse transform */ +extern SDError SDinvXform(RREAL iMtx[3][3], RREAL vMtx[3][3]); + +/* Transform and normalize direction (column) vector */ +extern SDError SDmapDir(FVECT resVec, RREAL vMtx[3][3], + const FVECT inpVec); + +/*################################################################*/ +/*######### DEPRECATED DEFINITIONS AWAITING PERMANENT REMOVAL #######*/ +/* * Header for BSDF i/o and access routines */ -#ifndef _RAD_BSDF_H_ -#define _RAD_BSDF_H_ +#include "mat4.h" /* up directions */ typedef enum { UDzneg=-3, @@ -17,10 +243,11 @@ typedef enum { } UpDir; /* BSDF coordinate calculation routines */ /* vectors always point away from surface */ -typedef int b_vecf(FVECT, int, void *); -typedef int b_ndxf(FVECT, void *); -typedef double b_radf(int, void *); +typedef int b_vecf2(FVECT v, int n, void *cd); +typedef int b_ndxf2(FVECT v, void *cd); +typedef double b_radf2(int n, void *cd); + /* Bidirectional Scattering Distribution Function */ struct BSDF_data { int ninc; /* number of incoming directions */ @@ -28,13 +255,13 @@ struct BSDF_data { float dim[3]; /* width, height, thickness (meters) */ char *mgf; /* geometric description (if any) */ void *ib_priv; /* input basis private data */ - b_vecf *ib_vec; /* get input vector from index */ - b_ndxf *ib_ndx; /* get input index from vector */ - b_radf *ib_ohm; /* get input radius for index */ + b_vecf2 *ib_vec; /* get input vector from index */ + b_ndxf2 *ib_ndx; /* get input index from vector */ + b_radf2 *ib_ohm; /* get input radius for index */ void *ob_priv; /* output basis private data */ - b_vecf *ob_vec; /* get output vector from index */ - b_ndxf *ob_ndx; /* get output index from vector */ - b_radf *ob_ohm; /* get output radius for index */ + b_vecf2 *ob_vec; /* get output vector from index */ + b_ndxf2 *ob_ndx; /* get output index from vector */ + b_radf2 *ob_ohm; /* get output radius for index */ float *bsdf; /* scattering distribution data */ }; /* bidirectional scattering distrib. func. */ @@ -54,4 +281,10 @@ extern int r_BSDF_outvec(FVECT v, struct BSDF_data *b, double rv, MAT4 xm); extern int getBSDF_xfm(MAT4 xm, FVECT nrm, UpDir ud, char *xfbuf); -#endif /* ! _RAD_BSDF_H_ */ +/*######### END DEPRECATED DEFINITIONS #######*/ +/*################################################################*/ + +#ifdef __cplusplus +} +#endif +#endif /* ! _BSDF_H_ */