00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "sphericalfunction_ies.h"
00024 #include "error.h"
00025 #include "mcdistribution.h"
00026
00027 namespace lux {
00028 IESSphericalFunction::IESSphericalFunction() {
00029 initDummy();
00030 }
00031
00032 IESSphericalFunction::IESSphericalFunction(const PhotometricDataIES& data, bool flipZ) {
00033 if( data.m_PhotometricType != PhotometricDataIES::PHOTOMETRIC_TYPE_C ) {
00034 luxError( LUX_UNIMPLEMENT, LUX_WARNING, "unsupported photometric type IES file, result may be wrong" );
00035 }
00036 vector<double> vertAngles = data.m_VerticalAngles;
00037 vector<double> horizAngles = data.m_HorizontalAngles;
00038 vector< vector<double> > values = data.m_CandelaValues;
00039
00040
00041 if( vertAngles[0] < 0.0 ) {
00042 for( u_int i = 0; i < vertAngles.size(); i++ ) {
00043 vertAngles[i] = vertAngles[i] + 90.0;
00044 }
00045 }
00046 if( vertAngles[0] > 0.0 ) {
00047 vertAngles.insert( vertAngles.begin(), vertAngles[0] - 1e-3 );
00048 for( u_int i = 0; i < values.size(); i++ ) {
00049 values[i].insert( values[i].begin(), 0.0 );
00050 }
00051 }
00052 if( vertAngles[vertAngles.size() - 1] < 180.0 ) {
00053 vertAngles.push_back( vertAngles[vertAngles.size() - 1] + 1e-3 );
00054 for( u_int i = 0; i < values.size(); i++ ) {
00055 values[i].push_back( 0.0 );
00056 }
00057 }
00058
00059 if( horizAngles[0] == 0.0 && horizAngles.size() == 1 ) {
00060
00061 }
00062 else if( horizAngles[0] == 0.0 ) {
00063 if( horizAngles[ horizAngles.size() - 1] == 90.0 ) {
00064 for( int i = horizAngles.size() - 2; i >= 0; i--) {
00065 horizAngles.push_back(180.0 - horizAngles[i]);
00066 vector<double> tmpVals = values[i];
00067 values.push_back(tmpVals);
00068 }
00069 }
00070 if( horizAngles[ horizAngles.size() - 1] == 180.0 ) {
00071 for( int i = horizAngles.size() - 2; i >= 0; i--) {
00072 horizAngles.push_back(360.0 - horizAngles[i]);
00073 vector<double> tmpVals = values[i];
00074 values.push_back(tmpVals);
00075 }
00076 }
00077 if( horizAngles[ horizAngles.size() - 1] != 360.0 ) {
00078 luxError( LUX_UNIMPLEMENT, LUX_ERROR, "unsupported horizontal angles in IES file" );
00079 initDummy();
00080 return;
00081 }
00082 }
00083 else {
00084 luxError( LUX_BADFILE, LUX_ERROR, "invalid horizontal angles in IES file" );
00085 initDummy();
00086 return;
00087 }
00088
00089
00090 float valueScale = data.m_CandelaMultiplier *
00091 data.BallastFactor *
00092 data.BallastLampPhotometricFactor;
00093 int nVFuncs = horizAngles.size();
00094 IrregularFunction1D** vFuncs = new IrregularFunction1D*[ nVFuncs ];
00095 int vFuncLength = vertAngles.size();
00096 float* vFuncX = new float[vFuncLength];
00097 float* vFuncY = new float[vFuncLength];
00098 float* uFuncX = new float[nVFuncs];
00099 float* uFuncY = new float[nVFuncs];
00100 for( int i = 0; i < nVFuncs; i++ ) {
00101 for( int j = 0; j < vFuncLength; j++ ) {
00102 vFuncX[ j ] = Clamp( Radians( vertAngles[ j ] ) * INV_PI, 0.f, 1.f );
00103 vFuncY[ j ] = values[ i ][ j ] * valueScale;
00104 }
00105
00106 vFuncs[ i ] = new IrregularFunction1D( vFuncX, vFuncY, vFuncLength );
00107
00108 uFuncX[ i ] = Clamp( Radians( horizAngles[ i ] ) * INV_TWOPI, 0.f, 1.f );
00109 uFuncY[ i ] = i;
00110 }
00111 delete[] vFuncX;
00112 delete[] vFuncY;
00113
00114 IrregularFunction1D* uFunc = new IrregularFunction1D( uFuncX, uFuncY, nVFuncs );
00115 delete[] uFuncX;
00116 delete[] uFuncY;
00117
00118
00119 int xRes = 512;
00120 int yRes = 256;
00121 TextureColor<float, 1>* img = new TextureColor<float, 1>[xRes*yRes];
00122 for( int y = 0; y < yRes; y++ ) {
00123 for( int x = 0; x < xRes; x++ ) {
00124 float s = ( x + .5f ) / float(xRes);
00125 float t = ( y + .5f ) / float(yRes);
00126 float du;
00127 int u1 = uFunc->IndexOf(s, &du);
00128 int u2 = min(nVFuncs - 1, u1 + 1);
00129 int tgtY = flipZ ? (yRes-1)-y : y;
00130 img[ x + tgtY*xRes ] =
00131 vFuncs[u1]->Eval(t) * (1.f - du) + vFuncs[u2]->Eval(t) * du;
00132 }
00133 }
00134 delete uFunc;
00135 for( int i = 0; i < nVFuncs; i++)
00136 delete vFuncs[i];
00137 delete[] vFuncs;
00138
00139 boost::shared_ptr< MIPMap<RGBColor> > ptr(
00140 new MIPMapFastImpl< RGBColor, TextureColor<float, 1> >( BILINEAR, xRes, yRes, &img[0] )
00141 );
00142 SetMipMap(ptr);
00143
00144 delete[] img;
00145 }
00146
00147 void IESSphericalFunction::initDummy() {
00148 TextureColor<float, 1> img[1] = {1.f};
00149 boost::shared_ptr< MIPMap<RGBColor> > ptr(
00150 new MIPMapFastImpl< RGBColor, TextureColor<float, 1> >( NEAREST, 1, 1, &img[0] )
00151 );
00152 SetMipMap(ptr);
00153 }
00154
00155 }