Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Haar.cc

Go to the documentation of this file.
00001 /*
00002         File:           Haar.cc
00003 
00004         Function:       Implementation of the Haar basis
00005 
00006         Author:         Andrew Willmott
00007 
00008         Notes:          
00009 */
00010 
00011 #include "Haar.h"
00012 #include "RadMethod.h"
00013 #include "gcl/Draw.h"
00014 
00015 #define DBG_COUT if (0) cerr
00016 
00017 #define RAD_SAMPLE_ERROR
00018 
00019 // --- HaarLink methods -------------------------------------------------------
00020 
00021 
00022 Bool HaarLink::CalcTransport()
00023 {
00024     if (gRadControl->quadLevel > 3)
00025         transport = From()->SampledFormFactor(8, To(), error);
00026     else
00027     {
00028         transport = From()->EstFormFactor(To());
00029         error = transport;
00030     }
00031 
00032     if (transport == 0.0 && error == 0.0)
00033         return(false);
00034 
00035     return(true);
00036 }
00037 
00038 Bool HaarLink::CalcVisibility(HRLink *parent, Bool reuse)
00039 {
00040     if (parent && (reuse || !NeedVisibility(parent)))
00041         visibility = parent->visibility;
00042     else
00043         visibility = From()->Visibility(To());
00044     
00045     transport *= visibility;
00046 
00047     return(true);
00048 }
00049 
00050 Void HaarLink::Gather()
00051 {
00052     To()->R += transport * From()->B;
00053 }
00054 
00055 GCLReal HaarLink::Error()
00056 {
00057     return(error);
00058 }
00059 
00060 GCLReal HaarLink::BFAError()
00061 {
00062     return(To()->area * error * 
00063         dot(kRadRGBToLum, To()->Reflectance() * From()->B));
00064 }
00065 
00066 Void HaarLink::Print(ostream &s)
00067 {
00068     HRLink::Print(s);
00069     s << transport << ' ' << visibility << ' ';
00070 }
00071 
00072 Void HaarLink::DrawLink(Renderer &r, GCLReal left, GCLReal top,
00073                         GCLReal right, GCLReal bottom, GCLReal weight)
00074 {
00075     r.SetColour(To()->Reflectance() * transport * visibility * weight);
00076 
00077     PaintRect(r, Coord(left, top), Coord(right, bottom));
00078 }
00079 
00080 
00081 // --- HaarElem methods -------------------------------------------------------
00082 
00083 
00084 Colour HaarElem::lastB;
00085 
00086 Void HaarElem::Add()
00087 {
00088     B += R;
00089 }
00090 
00091 Void HaarElem::Push()
00092 {
00093     Int i;
00094     
00095     for (i = 0; i < 4; i++)
00096         Child(i)->B = B;
00097 }
00098 
00099 Void HaarElem::Pull()
00100 {
00101     Int     i;
00102     
00103     B = vl_0;
00104     for (i = 0; i < 4; i++)
00105         B += Child(i)->B;
00106     B /= 4.0;
00107 }
00108 
00109 Void HaarElem::ClearB()
00110 {
00111     //  Save B for comparison to post push/pull B
00112     lastB = B;
00113     //  Initialise B to emittance of this patch.
00114     B = vl_0;
00115 }
00116 
00117 GCLReal HaarElem::Error()
00118 {
00119     return(dot(kRadRGBToLum, B - lastB));
00120 }
00121 
00122 Void HaarElem::ClearR()
00123 {
00124     R = vl_0;
00125 }
00126 
00127 Void HaarElem::CalcLeafRadiosity()
00128 {
00129     B = Emittance() + Reflectance() * B;
00130 }
00131 
00132 Void HaarElem::Print(ostream &s)
00133 {
00134     s << " + haar ";
00135     PrintRec(s);
00136 }
00137 
00138 Void HaarElem::PrintSelf(ostream &s)
00139 {
00140     HRMeshElem::PrintSelf(s);
00141     s << B << ' ';
00142 }
00143 
00144 Void HaarElem::ParseSelf(istream &s)
00145 {
00146     HRMeshElem::ParseSelf(s);
00147     s >> B;
00148 }
00149 
00150 Void HaarElem::SetParent(HierElem &itsParent)
00151 {
00152     HierElem::SetParent(itsParent);
00153 
00154     B = ((HaarElem &) itsParent).B; 
00155 }
00156 
00157 Colour HaarElem::SampleLeaf(Coord c)
00158 {
00159 
00160     if (gRadControl->gouraud)
00161     {
00162         Colour  c1, c2;
00163 
00164         c1 = Mix(VtxClr(0), VtxClr(3), c[0]); 
00165         c2 = Mix(VtxClr(1), VtxClr(2), c[0]); 
00166         return(Mix(c2, c1, c[1]));
00167     }
00168     else
00169         return(B);
00170 }
00171 
00172 Void HaarElem::EltSampleTransport(
00173         Int     numSamples,
00174         Point   p[],
00175         Vector  n[],
00176         Matd    &coeffs
00177     )
00178     // find coeffs s.t. dot(from->B, coeffs) = irradiance
00179     // at p, n.
00180 {
00181     Int     i;
00182 
00183     for (i = 0; i < numSamples; i++)
00184         coeffs[i][0] = ApproxPatchFactor(p[i], n[i]);
00185     DBG_COUT << "haar: sample coeffs = " << coeffs << endl;
00186 }
00187 
00188 GCLReal HaarElem::EltCalcTransport(HRElem *from, Matd &coeffs)
00189 {
00190     if (from == this)
00191     {
00192         // no self-reflection for haar...
00193         coeffs = vl_0;
00194         return(0.0);
00195     }
00196 
00197 #ifndef RAD_SAMPLE_ERROR
00198     from->EltSampleTransport(1, &centre, &normal, coeffs);
00199     DBG_COUT << "haar: transport coeffs = " << coeffs << endl;
00200     return(coeffs[0][0]);
00201 #else
00202     GCLReal     error;
00203     Point       p[16];
00204     Vector      n[16];
00205     static Matd t;
00206     Int         i, samples;
00207 
00208 #ifdef RAD_SC
00209     // sample at 3 or 4 corners and centre.
00210 
00211     for (i = 0; i < Sides(); i++)
00212     {
00213         p[i] = Vertex(i);
00214         n[i] = normal;
00215     }
00216     p[i] = centre;
00217     n[i] = normal;
00218     samples = i + 1;
00219 #else
00220     samples = 16;
00221     SetVisPoints(p);
00222     for (i = 0; i < 16; i++)
00223         n[i] = normal;
00224 #endif
00225     t.SetSize(samples, from->NumCoeffs());
00226 
00227     from->EltSampleTransport(samples, p, n, t);
00228 
00229     // find (Linf) error in samples
00230     error = VecError(col(t, 0));
00231     // average samples to get coeffs...
00232     coeffs[0] = t[0];
00233     for (i = 1; i < t.Rows(); i++)
00234         coeffs[0] += t[i];
00235     coeffs[0] /= t.Rows();
00236 
00237     return(error);
00238 #endif
00239 }
00240 
00241 Void HaarElem::AddIrradiance(const Colour &E, const Vector &m)
00242 {
00243     GCLReal     temp;
00244 
00245     temp = dot(m, normal);
00246     if (temp > 0.0)
00247         R += temp * E;
00248 }
00249 
00250 Colour HaarElem::GetPower(const Vector &m)
00251 {
00252     return(B * EltProjArea(m));
00253 }
00254 
00255 Void HaarElem::DistributeColours()
00256 {
00257     SetColour(B);
00258 
00259     if (HasChildren())
00260     {
00261         Child(0)->DistributeColours();
00262         Child(1)->DistributeColours();
00263         Child(2)->DistributeColours();
00264         Child(3)->DistributeColours();
00265     }
00266 }
00267 
00268 Void HaarElem::DistributeColoursBest(ShadeInfo &shadeInfo)
00269 {
00270     if (gRadControl->bestLevels == 0)
00271     {
00272         // for now we return. eventually would like to resample at vertices
00273         // same as the clusters. (only perhaps avoiding duplicate samples.)
00274         DistributeColours();
00275         return;
00276     }
00277 
00278     // Here we apply the leaf element irradiances to the leaf face clusters
00279 
00280     if (!links.IsEmpty())
00281         shadeInfo.linkStack.Push(&links);
00282 
00283     if (IsLeaf() && shadeInfo.level >= gRadControl->bestLevels)
00284     {
00285         Int         i, nlinks = 0;
00286         HRLinkIter  l;
00287             
00288         Point       centreOff, srcPt;
00289         Vector      r;
00290         GCLReal     dp, r2;
00291         Colour      E;
00292 
00293         // find face's normal, pos & area in WCS
00294 
00295         centreOff = centre;
00296         centreOff += 1e-6 * normal;
00297         colour = cBlack;
00298 
00299         // traverse all links, do final gather
00300         for (i = 0; i < shadeInfo.linkStack.NumItems(); i++)
00301             for (l.Begin(*shadeInfo.linkStack[i]); !l.AtEnd(); l.Inc())
00302             {
00303                 HRElem *src = l.Data().from;
00304 
00305                 nlinks++;               
00306                 srcPt = src->EltCentre();
00307                 r = srcPt - centre;
00308                 dp = dot(r, normal);
00309                 r2 = sqrlen(r);
00310 
00311                 if (dp > 0 && r2 > 0)
00312                 {
00313                     E = src->GetPower(-r);
00314                     E *= dp / (sqr(r2) * vl_pi + src->EltArea());
00315 
00316                     if (!gRadControl->bestVisPass)
00317                         E *= l.Data().visibility;
00318                     else
00319                     {
00320                         dp = l.Data().visibility;
00321                         if (dp == 0.0)
00322                             E = vl_0;
00323                         else if (dp < 1.0)  // dot(kRadRGBToLum, E) > 0.01
00324                         {
00325                             r /= sqrt(r2) * 1e6;
00326                             srcPt -= r;
00327                             if (gRadControl->radObject->
00328                                 IntersectsWithRay(srcPt, centreOff))
00329                                     E = vl_0;
00330                             gRadControl->rays++;
00331                         }
00332                         else
00333                             E *= dp;
00334                     }
00335                     colour += E * Reflectance();
00336                 }
00337             }
00338 
00339         colour += Emittance();
00340     }
00341     else
00342     {
00343         Bool amSubdividing = IsLeaf();
00344 
00345         if (amSubdividing)
00346         {
00347             shadeInfo.level++;
00348 
00349             flags.Set(hrIntNode);
00350             if (!HasChildren())
00351                 Subdivide();
00352         }
00353 
00354         Child(0)->DistributeColoursBest(shadeInfo);
00355         Child(1)->DistributeColoursBest(shadeInfo);
00356         Child(2)->DistributeColoursBest(shadeInfo);
00357         Child(3)->DistributeColoursBest(shadeInfo);
00358 
00359         if (amSubdividing)
00360             shadeInfo.level--;
00361     }
00362 
00363     if (!links.IsEmpty())
00364         shadeInfo.linkStack.Pop();
00365 }

Generated at Sat Aug 5 00:26:51 2000 for Radiator by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000