/* bsdf.c: Bidirectional Reflectance Distribution Functions */ #include "bsdf.h" #include "pools.h" #include "vector.h" #include "error.h" #ifdef NOPOOLS #define NEWBSDF() (BSDF *)Alloc(sizeof(BSDF)) #define DISPOSEBSDF(ptr) Free((char *)ptr, sizeof(BSDF)) #else static POOL *bsdfPool = (POOL *)NULL; #define NEWBSDF() (BSDF *)NewPoolCell(sizeof(BSDF), 0, "bsdfs", &bsdfPool) #define DISPOSEBSDF(ptr) Dispose((char *)ptr, &bsdfPool) #endif /* Creates a BSDF instance with given data and methods. A pointer * to the created BSDF struct is returned. */ BSDF *BsdfCreate(void *data, BSDF_METHODS *methods) { BSDF *bsdf; // bsdf = NEWBSDF(); bsdf = (BSDF*)malloc(sizeof(BSDF)); bsdf->data = data; bsdf->methods = methods; return bsdf; } /* Creates and returns a duplicate of the given BSDF */ BSDF *BsdfDuplicate(BSDF *obsdf) { BSDF *bsdf; if (!obsdf) return obsdf; bsdf = NEWBSDF(); bsdf->data = obsdf->methods->Duplicate(obsdf->data); bsdf->methods = obsdf->methods; return bsdf; } /* Creates an editor widget for the BSDF, returns the Widget casted * to a void * in order not to have to include all X window system files. */ void *BsdfCreateEditor(void *parent, BSDF *bsdf) { if (!bsdf) Fatal(-1, "BsdfCreateEditor", "NULL bsdf pointer passed."); return bsdf->methods->CreateEditor(parent, bsdf->data); } /* disposes of the memory occupied by the BSDF instance */ void BsdfDestroy(BSDF *bsdf) { if (!bsdf) return; bsdf->methods->Destroy(bsdf->data); DISPOSEBSDF(bsdf); } /* Returns the scattered power of the BSDF, depending on the flags */ COLOR BsdfScatteredPower(BSDF *bsdf, HITREC *hit, VECTOR *in, BSDFFLAGS flags) { COLOR refl; COLORCLEAR(refl); if (bsdf && bsdf->methods->ScatteredPower) refl = bsdf->methods->ScatteredPower(bsdf->data, hit, in, flags); return refl; } int BsdfIsTextured(BSDF *bsdf) { if (bsdf && bsdf->methods->IsTextured) return bsdf->methods->IsTextured(bsdf->data); return FALSE; } int BsdfShadingFrame(BSDF *bsdf, HITREC *hit, VECTOR *X, VECTOR *Y, VECTOR *Z) { if (bsdf && bsdf->methods->ShadingFrame) { return bsdf->methods->ShadingFrame(bsdf->data, hit, X, Y, Z); } return FALSE; } void BsdfIndexOfRefraction(BSDF *bsdf, REFRACTIONINDEX *index) { if (bsdf && bsdf->methods->IndexOfRefraction) { bsdf->methods->IndexOfRefraction(bsdf->data, index); } else { index->nr = 1.0; index->ni = 0.0; /* Vacuum */ } } /* Bsdf evaluations */ COLOR BsdfEval(BSDF *bsdf, HITREC *hit, BSDF *inBsdf, BSDF *outBsdf, VECTOR *in, VECTOR *out, BSDFFLAGS flags) { if (bsdf && bsdf->methods->Eval) return bsdf->methods->Eval(bsdf->data, hit, inBsdf, outBsdf, in, out, flags); else { static COLOR refl; COLORCLEAR(refl); return refl; } } /* * BsdfEvalComponents : * Evaluates all requested components of the BSDF separately and * stores the result in 'colArray'. * Total evaluation is returned. */ extern COLOR BsdfEvalComponents(BSDF *bsdf, HITREC *hit, BSDF *inBsdf, BSDF *outBsdf, VECTOR *in, VECTOR *out, BSDFFLAGS flags, COLOR *colArray) { /* Some caching optimisation could be used here */ /* if (bsdf && bsdf->methods->EvalComponents) return bsdf->methods->EvalComponents(bsdf->data, inBsdf, outBsdf, in, out, normal, flags, colArray); else */ COLOR result, empty; int i; BSDFFLAGS thisFlag; COLORCLEAR(empty); COLORCLEAR(result); for(i = 0; i < BSDFCOMPONENTS; i++) { thisFlag = BSDF_INDEXTOCOMP(i); if(flags & thisFlag) { colArray[i] = BsdfEval(bsdf, hit, inBsdf, outBsdf, in, out, thisFlag); COLORADD(result, colArray[i], result); } else { colArray[i] = empty; /* Set to 0 for safety */ } } return result; } /* Sampling and pdf evaluation */ VECTOR BsdfSample(BSDF *bsdf, HITREC *hit, BSDF *inBsdf, BSDF *outBsdf, VECTOR *in, int doRussianRoulette, BSDFFLAGS flags, double x_1, double x_2, double *pdf) { if (bsdf && bsdf->methods->Sample) return bsdf->methods->Sample(bsdf->data, hit, inBsdf, outBsdf, in, doRussianRoulette, flags, x_1, x_2, pdf); else { VECTOR dummy = {0., 0., 0.}; *pdf = 0; return dummy; } } void BsdfEvalPdf(BSDF *bsdf, HITREC *hit, BSDF *inBsdf, BSDF *outBsdf, VECTOR *in, VECTOR *out, BSDFFLAGS flags, double *pdf, double *pdfRR) { if (bsdf && bsdf->methods->EvalPdf) bsdf->methods->EvalPdf(bsdf->data, hit, inBsdf, outBsdf, in, out, flags, pdf, pdfRR); else { *pdf = 0; } } /* Print the bsdf data the to specified file pointer */ void BsdfPrint(FILE *out, BSDF *bsdf) { if (!bsdf) fprintf(out, "(NULL BSDF)\n"); else bsdf->methods->Print(out, bsdf->data); }