/* brdf.c: Bidirectional Reflectance Distribution Functions */ #include "brdf.h" #include "pools.h" #include "vector.h" #include "error.h" #ifdef NOPOOLS #define NEWBRDF() (BRDF *)Alloc(sizeof(BRDF)) #define DISPOSEBRDF(ptr) Free((char *)ptr, sizeof(BRDF)) #else static POOL *brdfPool = (POOL *)NULL; #define NEWBRDF() (BRDF *)NewPoolCell(sizeof(BRDF), 0, "brdfs", &brdfPool) #define DISPOSEBRDF(ptr) Dispose((char *)ptr, &brdfPool) #endif /* Creates a BRDF instance with given data and methods. A pointer * to the created BRDF struct is returned. */ BRDF *BrdfCreate(void *data, BRDF_METHODS *methods) { BRDF *brdf; brdf = NEWBRDF(); brdf->data = data; brdf->methods = methods; return brdf; } /* Creates and returns a duplicate of the given BRDF */ BRDF *BrdfDuplicate(BRDF *obrdf) { BRDF *brdf; if (!obrdf) return obrdf; brdf = NEWBRDF(); brdf->data = obrdf->methods->Duplicate(obrdf->data); brdf->methods = obrdf->methods; return brdf; } /* Creates an editor widget for the BRDF, returns the Widget casted * to a void * in order not to have to include all X window system files. */ void *BrdfCreateEditor(void *parent, BRDF *brdf) { if (!brdf) Fatal(-1, "BrdfCreateEditor", "NULL brdf pointer passed."); return brdf->methods->CreateEditor(parent, brdf->data); } /* disposes of the memory occupied by the BRDF instance */ void BrdfDestroy(BRDF *brdf) { if (!brdf) return; brdf->methods->Destroy(brdf->data); DISPOSEBRDF(brdf); } /* Returns the diffuse reflectance of the BRDF */ COLOR BrdfReflectance(BRDF *brdf, XXDFFLAGS flags) { if (brdf && brdf->methods->Reflectance) { COLOR test = brdf->methods->Reflectance(brdf->data, flags); if (! finite(COLORAVERAGE(test))) { Fatal(-1, "BrdfReflectance", "Oops - test Rd is not finite!"); } return test; } else { static COLOR refl; COLORCLEAR(refl); return refl; } } /* Brdf evaluations */ COLOR BrdfEval(BRDF *brdf, VECTOR *in, VECTOR *out, VECTOR *normal, XXDFFLAGS flags) { if (brdf && brdf->methods->Eval) return brdf->methods->Eval(brdf->data, in, out, normal, flags); else { static COLOR refl; COLORCLEAR(refl); return refl; } } /* Sampling and pdf evaluation */ VECTOR BrdfSample(BRDF *brdf, VECTOR *in, VECTOR *normal, int doRussianRoulette, XXDFFLAGS flags, double x_1, double x_2, double *pdf) { if (brdf && brdf->methods->Sample) return brdf->methods->Sample(brdf->data, in, normal, doRussianRoulette, flags, x_1, x_2, pdf); else { VECTOR dummy = {0., 0., 0.}; *pdf = 0; return dummy; } } void BrdfEvalPdf(BRDF *brdf, VECTOR *in, VECTOR *out, VECTOR *normal, XXDFFLAGS flags, double *pdf, double *pdfRR) { if (brdf && brdf->methods->EvalPdf) brdf->methods->EvalPdf(brdf->data, in, out, normal, flags, pdf, pdfRR); else { *pdf = 0; } } /* Print the brdf data the to specified file pointer */ void BrdfPrint(FILE *out, BRDF *brdf) { if (!brdf) fprintf(out, "(NULL BRDF)\n"); else brdf->methods->Print(out, brdf->data); }