00001 /*
00002 File: GenLink.cc
00003
00004 Function:
00005
00006 Author: Andrew Willmott
00007
00008 Notes:
00009 */
00010
00011 #include "GenLink.h"
00012 #include "HRElem.h"
00013 #include "Cluster.h"
00014 #include "RadMethod.h"
00015
00016 #define DBG_COUT if (0) cerr
00017
00018 #define RAD_NON_ISO_SOURCE
00019 #define RAD_NON_ISO_DEST
00020 // the above should always be defined, except for experiments showing how
00021 // bad the isotropic assumption is =)
00022
00023 // --- GenLink methods ----------------------------------------------------
00024
00025
00026 Bool GenLink::CalcTransport()
00027 {
00028 Assert(to->NumCoeffs() == 1, "can't handle non-haar receiver yet");
00029 Assert(from->NumCoeffs() == 1, "can't handle non-haar source yet");
00030 Matd T(to->NumCoeffs(), from->NumCoeffs(), &transport);
00031
00032 error = to->EltCalcTransport(from, T);
00033
00034 Assert(vl_is_finite(transport), "bad transport coeff!!!");
00035
00036 DBG_COUT << "transport = " << T << "error = " << error << ", vis = "
00037 << visibility << endl;
00038
00039 #ifdef RAD_VIS
00040 if (gRadControl->showLinks)
00041 {
00042 Int s1 = from->eltHighlight, s2 = to->eltHighlight;
00043
00044 from->SetHighlight(3);
00045 to->SetHighlight(2);
00046
00047 RM_DISPLAY_START;
00048 gRadControl->radObject->display->Begin(renLines)
00049 .C(cRed)
00050 .P(from->EltCentre()).P(to->EltCentre())
00051 .End();
00052 RM_DISPLAY_END;
00053
00054 RM_OUT1("Link transport/error: " << transport << " / " << error);
00055 RM_OUT2("Link Power: " << from->EltBA() << " -> " << to->EltBA());
00056 RM_OUT3(BFAError());
00057 if (RM_PAUSE) return(false);
00058
00059 from->SetHighlight(s1);
00060 to->SetHighlight(s2);
00061 }
00062 #endif
00063
00064 // if there's some error, keep the link around even if it's zero
00065 return(transport > 0.0 || error > 0.0);
00066 }
00067
00068 Bool GenLink::CalcVisibility(HRLink *parent, Bool reuse)
00069 {
00070 Bool result = HRLink::CalcVisibility(parent, reuse);
00071
00072 transport *= visibility;
00073
00074 return(result);
00075 }
00076
00077 Void GenLink::Gather()
00078 {
00079 Colour srcB;
00080
00081 // find irradiance at (to)
00082 // XXX generalise
00083 srcB = from->B_Coeffs()[0] * transport;
00084
00085 Assert(vl_is_finite(srcB[0]) && vl_is_finite(srcB[1]) && vl_is_finite(srcB[2]),
00086 "bad srcB coeffs");
00087
00088 #ifdef RAD_NON_ISO_DEST
00089 if (to->IsCluster() && (from != to))
00090 {
00091 // destination is a cluster: push radiosity to leaves to get
00092 // proper directional distribution on the destination...
00093
00094 Vector r = from->EltCentre() - to->EltCentre();
00095 GCLReal rLen = len(r);
00096
00097 // r is unit vector from to -> from
00098 if (rLen > 0.0)
00099 r /= rLen;
00100 else
00101 Expect(false, "zero separation between source and destination elems.");
00102
00103 if (sqrlen(srcB) > 0.0)
00104 to->AddIrradiance(srcB, r);
00105 }
00106 else
00107 #endif
00108 {
00109 // XXX generalise
00110 to->R_Coeffs()[0] += srcB;
00111 DBG_COUT << "Gather: Dest(" << to->flags << ") updated to "
00112 << to->R_Coeffs()[0] << " from "
00113 << from->B_Coeffs()[0] << " (" << to->flags << ")" << endl;
00114 }
00115
00116 #ifdef DEBUG
00117 srcB = (to->R_Coeffs()[0]);
00118 Assert(vl_is_finite(srcB[0]) && vl_is_finite(srcB[1]) && vl_is_finite(srcB[2]),
00119 "bad R coeffs");
00120 #endif
00121 }
00122
00123 GCLReal GenLink::Error()
00124 {
00125 return(error);
00126 }
00127
00128 GCLReal GenLink::BFAError()
00129 {
00130 GCLReal result;
00131
00132 DBG_COUT << "BFErr: area error rho from->BA = "
00133 << to->EltArea() << ' '
00134 << error << ' '
00135 << to->EltRho() << ' '
00136 << from->EltBA() << endl;
00137
00138 result = to->EltArea() * error *
00139 dot(kRadRGBToLum, to->EltRho() * from->EltBA() / from->EltArea());
00140
00141 DBG_COUT << "BFErr: result = " << result << endl;
00142
00143 return(result);
00144 }
00145
00146 RefChoice GenLink::RefineOracle()
00147 {
00148 // force refinement of mixed clusters, a la Gibson
00149
00150 if (from->flags.AreSet(hrMixed))
00151 {
00152 if (from == to)
00153 return(kSubBoth);
00154 else
00155 return(kSubFrom);
00156 }
00157 else
00158 return(HRLink::RefineOracle());
00159 }