Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/util/util_ies.cpp')
-rw-r--r--intern/cycles/util/util_ies.cpp668
1 files changed, 335 insertions, 333 deletions
diff --git a/intern/cycles/util/util_ies.cpp b/intern/cycles/util/util_ies.cpp
index 277045d9bc4..ff5c709b406 100644
--- a/intern/cycles/util/util_ies.cpp
+++ b/intern/cycles/util/util_ies.cpp
@@ -30,374 +30,376 @@ template class GuardedAllocator<char>;
bool IESFile::load(ustring ies)
{
- clear();
- if(!parse(ies) || !process()) {
- clear();
- return false;
- }
- return true;
+ clear();
+ if (!parse(ies) || !process()) {
+ clear();
+ return false;
+ }
+ return true;
}
void IESFile::clear()
{
- intensity.clear();
- v_angles.clear();
- h_angles.clear();
+ intensity.clear();
+ v_angles.clear();
+ h_angles.clear();
}
int IESFile::packed_size()
{
- if(v_angles.size() && h_angles.size() > 0) {
- return 2 + h_angles.size() + v_angles.size() + h_angles.size()*v_angles.size();
- }
- return 0;
+ if (v_angles.size() && h_angles.size() > 0) {
+ return 2 + h_angles.size() + v_angles.size() + h_angles.size() * v_angles.size();
+ }
+ return 0;
}
void IESFile::pack(float *data)
{
- if(v_angles.size() && h_angles.size()) {
- *(data++) = __int_as_float(h_angles.size());
- *(data++) = __int_as_float(v_angles.size());
-
- memcpy(data, &h_angles[0], h_angles.size()*sizeof(float));
- data += h_angles.size();
- memcpy(data, &v_angles[0], v_angles.size()*sizeof(float));
- data += v_angles.size();
-
- for(int h = 0; h < intensity.size(); h++) {
- memcpy(data, &intensity[h][0], v_angles.size()*sizeof(float));
- data += v_angles.size();
- }
- }
+ if (v_angles.size() && h_angles.size()) {
+ *(data++) = __int_as_float(h_angles.size());
+ *(data++) = __int_as_float(v_angles.size());
+
+ memcpy(data, &h_angles[0], h_angles.size() * sizeof(float));
+ data += h_angles.size();
+ memcpy(data, &v_angles[0], v_angles.size() * sizeof(float));
+ data += v_angles.size();
+
+ for (int h = 0; h < intensity.size(); h++) {
+ memcpy(data, &intensity[h][0], v_angles.size() * sizeof(float));
+ data += v_angles.size();
+ }
+ }
}
class IESTextParser {
-public:
- vector<char> text;
- char *data;
-
- IESTextParser(ustring str)
- : text(str.begin(), str.end())
- {
- std::replace(text.begin(), text.end(), ',', ' ');
- data = strstr(&text[0], "\nTILT=");
- }
-
- bool eof() {
- return (data == NULL) || (data[0] == '\0');
- }
-
- double get_double() {
- if(eof()) {
- return 0.0;
- }
- char *old_data = data;
- double val = strtod(data, &data);
- if(data == old_data) {
- data = NULL;
- return 0.0;
- }
- return val;
- }
-
- long get_long() {
- if(eof()) {
- return 0;
- }
- char *old_data = data;
- long val = strtol(data, &data, 10);
- if(data == old_data) {
- data = NULL;
- return 0;
- }
- return val;
- }
+ public:
+ vector<char> text;
+ char *data;
+
+ IESTextParser(ustring str) : text(str.begin(), str.end())
+ {
+ std::replace(text.begin(), text.end(), ',', ' ');
+ data = strstr(&text[0], "\nTILT=");
+ }
+
+ bool eof()
+ {
+ return (data == NULL) || (data[0] == '\0');
+ }
+
+ double get_double()
+ {
+ if (eof()) {
+ return 0.0;
+ }
+ char *old_data = data;
+ double val = strtod(data, &data);
+ if (data == old_data) {
+ data = NULL;
+ return 0.0;
+ }
+ return val;
+ }
+
+ long get_long()
+ {
+ if (eof()) {
+ return 0;
+ }
+ char *old_data = data;
+ long val = strtol(data, &data, 10);
+ if (data == old_data) {
+ data = NULL;
+ return 0;
+ }
+ return val;
+ }
};
bool IESFile::parse(ustring ies)
{
- if(ies.empty()) {
- return false;
- }
-
- IESTextParser parser(ies);
- if(parser.eof()) {
- return false;
- }
-
- /* Handle the tilt data block. */
- if(strncmp(parser.data, "\nTILT=INCLUDE", 13) == 0) {
- parser.data += 13;
- parser.get_double(); /* Lamp to Luminaire geometry */
- int num_tilt = parser.get_long(); /* Amount of tilt angles and factors */
- /* Skip over angles and factors. */
- for(int i = 0; i < 2*num_tilt; i++) {
- parser.get_double();
- }
- }
- else {
- /* Skip to next line. */
- parser.data = strstr(parser.data+1, "\n");
- }
-
- if(parser.eof()) {
- return false;
- }
- parser.data++;
-
- parser.get_long(); /* Number of lamps */
- parser.get_double(); /* Lumens per lamp */
- double factor = parser.get_double(); /* Candela multiplier */
- int v_angles_num = parser.get_long(); /* Number of vertical angles */
- int h_angles_num = parser.get_long(); /* Number of horizontal angles */
- type = (IESType) parser.get_long(); /* Photometric type */
-
- /* TODO(lukas): Test whether the current type B processing can also deal with type A files.
- * In theory the only difference should be orientation which we ignore anyways, but with IES you never know...
- */
- if(type != TYPE_B && type != TYPE_C) {
- return false;
- }
-
- parser.get_long(); /* Unit of the geometry data */
- parser.get_double(); /* Width */
- parser.get_double(); /* Length */
- parser.get_double(); /* Height */
- factor *= parser.get_double(); /* Ballast factor */
- factor *= parser.get_double(); /* Ballast-Lamp Photometric factor */
- parser.get_double(); /* Input Watts */
-
- /* Intensity values in IES files are specified in candela (lumen/sr), a photometric quantity.
- * Cycles expects radiometric quantities, though, which requires a conversion.
- * However, the Luminous efficacy (ratio of lumens per Watt) depends on the spectral distribution
- * of the light source since lumens take human perception into account.
- * Since this spectral distribution is not known from the IES file, a typical one must be assumed.
- * The D65 standard illuminant has a Luminous efficacy of 177.83, which is used here to convert to Watt/sr.
- * A more advanced approach would be to add a Blackbody Temperature input to the node and numerically
- * integrate the Luminous efficacy from the resulting spectral distribution.
- * Also, the Watt/sr value must be multiplied by 4*pi to get the Watt value that Cycles expects
- * for lamp strength. Therefore, the conversion here uses 4*pi/177.83 as a Candela to Watt factor.
- */
- factor *= 0.0706650768394;
-
- v_angles.reserve(v_angles_num);
- for(int i = 0; i < v_angles_num; i++) {
- v_angles.push_back((float) parser.get_double());
- }
-
- h_angles.reserve(h_angles_num);
- for(int i = 0; i < h_angles_num; i++) {
- h_angles.push_back((float) parser.get_double());
- }
-
- intensity.resize(h_angles_num);
- for(int i = 0; i < h_angles_num; i++) {
- intensity[i].reserve(v_angles_num);
- for(int j = 0; j < v_angles_num; j++) {
- intensity[i].push_back((float) (factor * parser.get_double()));
- }
- }
-
- return !parser.eof();
+ if (ies.empty()) {
+ return false;
+ }
+
+ IESTextParser parser(ies);
+ if (parser.eof()) {
+ return false;
+ }
+
+ /* Handle the tilt data block. */
+ if (strncmp(parser.data, "\nTILT=INCLUDE", 13) == 0) {
+ parser.data += 13;
+ parser.get_double(); /* Lamp to Luminaire geometry */
+ int num_tilt = parser.get_long(); /* Amount of tilt angles and factors */
+ /* Skip over angles and factors. */
+ for (int i = 0; i < 2 * num_tilt; i++) {
+ parser.get_double();
+ }
+ }
+ else {
+ /* Skip to next line. */
+ parser.data = strstr(parser.data + 1, "\n");
+ }
+
+ if (parser.eof()) {
+ return false;
+ }
+ parser.data++;
+
+ parser.get_long(); /* Number of lamps */
+ parser.get_double(); /* Lumens per lamp */
+ double factor = parser.get_double(); /* Candela multiplier */
+ int v_angles_num = parser.get_long(); /* Number of vertical angles */
+ int h_angles_num = parser.get_long(); /* Number of horizontal angles */
+ type = (IESType)parser.get_long(); /* Photometric type */
+
+ /* TODO(lukas): Test whether the current type B processing can also deal with type A files.
+ * In theory the only difference should be orientation which we ignore anyways, but with IES you never know...
+ */
+ if (type != TYPE_B && type != TYPE_C) {
+ return false;
+ }
+
+ parser.get_long(); /* Unit of the geometry data */
+ parser.get_double(); /* Width */
+ parser.get_double(); /* Length */
+ parser.get_double(); /* Height */
+ factor *= parser.get_double(); /* Ballast factor */
+ factor *= parser.get_double(); /* Ballast-Lamp Photometric factor */
+ parser.get_double(); /* Input Watts */
+
+ /* Intensity values in IES files are specified in candela (lumen/sr), a photometric quantity.
+ * Cycles expects radiometric quantities, though, which requires a conversion.
+ * However, the Luminous efficacy (ratio of lumens per Watt) depends on the spectral distribution
+ * of the light source since lumens take human perception into account.
+ * Since this spectral distribution is not known from the IES file, a typical one must be assumed.
+ * The D65 standard illuminant has a Luminous efficacy of 177.83, which is used here to convert to Watt/sr.
+ * A more advanced approach would be to add a Blackbody Temperature input to the node and numerically
+ * integrate the Luminous efficacy from the resulting spectral distribution.
+ * Also, the Watt/sr value must be multiplied by 4*pi to get the Watt value that Cycles expects
+ * for lamp strength. Therefore, the conversion here uses 4*pi/177.83 as a Candela to Watt factor.
+ */
+ factor *= 0.0706650768394;
+
+ v_angles.reserve(v_angles_num);
+ for (int i = 0; i < v_angles_num; i++) {
+ v_angles.push_back((float)parser.get_double());
+ }
+
+ h_angles.reserve(h_angles_num);
+ for (int i = 0; i < h_angles_num; i++) {
+ h_angles.push_back((float)parser.get_double());
+ }
+
+ intensity.resize(h_angles_num);
+ for (int i = 0; i < h_angles_num; i++) {
+ intensity[i].reserve(v_angles_num);
+ for (int j = 0; j < v_angles_num; j++) {
+ intensity[i].push_back((float)(factor * parser.get_double()));
+ }
+ }
+
+ return !parser.eof();
}
bool IESFile::process_type_b()
{
- vector<vector<float> > newintensity;
- newintensity.resize(v_angles.size());
- for(int i = 0; i < v_angles.size(); i++) {
- newintensity[i].reserve(h_angles.size());
- for(int j = 0; j < h_angles.size(); j++) {
- newintensity[i].push_back(intensity[j][i]);
- }
- }
- intensity.swap(newintensity);
- h_angles.swap(v_angles);
-
- float h_first = h_angles[0], h_last = h_angles[h_angles.size()-1];
- if(h_last != 90.0f) {
- return false;
- }
-
- if(h_first == 0.0f) {
- /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
- * full 180° range. */
- vector<float> new_h_angles;
- vector<vector<float> > new_intensity;
- int hnum = h_angles.size();
- new_h_angles.reserve(2*hnum-1);
- new_intensity.reserve(2*hnum-1);
- for(int i = hnum-1; i > 0; i--) {
- new_h_angles.push_back(90.0f - h_angles[i]);
- new_intensity.push_back(intensity[i]);
- }
- for(int i = 0; i < hnum; i++) {
- new_h_angles.push_back(90.0f + h_angles[i]);
- new_intensity.push_back(intensity[i]);
- }
- h_angles.swap(new_h_angles);
- intensity.swap(new_intensity);
- }
- else if(h_first == -90.0f) {
- /* We have full 180° coverage, so just shift to match the angle range convention. */
- for(int i = 0; i < h_angles.size(); i++) {
- h_angles[i] += 90.0f;
- }
- }
- /* To get correct results with the cubic interpolation in the kernel, the horizontal range
- * has to cover all 360°. Therefore, we copy the 0° entry to 360° to ensure full coverage
- * and seamless interpolation. */
- h_angles.push_back(360.0f);
- intensity.push_back(intensity[0]);
-
- float v_first = v_angles[0], v_last = v_angles[v_angles.size()-1];
- if(v_last != 90.0f) {
- return false;
- }
-
- if(v_first == 0.0f) {
- /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
- * full 180° range. */
- vector<float> new_v_angles;
- int hnum = h_angles.size();
- int vnum = v_angles.size();
- new_v_angles.reserve(2*vnum-1);
- for(int i = vnum-1; i > 0; i--) {
- new_v_angles.push_back(90.0f - v_angles[i]);
- }
- for(int i = 0; i < vnum; i++) {
- new_v_angles.push_back(90.0f + v_angles[i]);
- }
- for(int i = 0; i < hnum; i++) {
- vector<float> new_intensity;
- new_intensity.reserve(2*vnum-1);
- for(int j = vnum-2; j >= 0; j--) {
- new_intensity.push_back(intensity[i][j]);
- }
- new_intensity.insert(new_intensity.end(), intensity[i].begin(), intensity[i].end());
- intensity[i].swap(new_intensity);
- }
- v_angles.swap(new_v_angles);
- }
- else if(v_first == -90.0f) {
- /* We have full 180° coverage, so just shift to match the angle range convention. */
- for(int i = 0; i < v_angles.size(); i++) {
- v_angles[i] += 90.0f;
- }
- }
-
- return true;
+ vector<vector<float>> newintensity;
+ newintensity.resize(v_angles.size());
+ for (int i = 0; i < v_angles.size(); i++) {
+ newintensity[i].reserve(h_angles.size());
+ for (int j = 0; j < h_angles.size(); j++) {
+ newintensity[i].push_back(intensity[j][i]);
+ }
+ }
+ intensity.swap(newintensity);
+ h_angles.swap(v_angles);
+
+ float h_first = h_angles[0], h_last = h_angles[h_angles.size() - 1];
+ if (h_last != 90.0f) {
+ return false;
+ }
+
+ if (h_first == 0.0f) {
+ /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
+ * full 180° range. */
+ vector<float> new_h_angles;
+ vector<vector<float>> new_intensity;
+ int hnum = h_angles.size();
+ new_h_angles.reserve(2 * hnum - 1);
+ new_intensity.reserve(2 * hnum - 1);
+ for (int i = hnum - 1; i > 0; i--) {
+ new_h_angles.push_back(90.0f - h_angles[i]);
+ new_intensity.push_back(intensity[i]);
+ }
+ for (int i = 0; i < hnum; i++) {
+ new_h_angles.push_back(90.0f + h_angles[i]);
+ new_intensity.push_back(intensity[i]);
+ }
+ h_angles.swap(new_h_angles);
+ intensity.swap(new_intensity);
+ }
+ else if (h_first == -90.0f) {
+ /* We have full 180° coverage, so just shift to match the angle range convention. */
+ for (int i = 0; i < h_angles.size(); i++) {
+ h_angles[i] += 90.0f;
+ }
+ }
+ /* To get correct results with the cubic interpolation in the kernel, the horizontal range
+ * has to cover all 360°. Therefore, we copy the 0° entry to 360° to ensure full coverage
+ * and seamless interpolation. */
+ h_angles.push_back(360.0f);
+ intensity.push_back(intensity[0]);
+
+ float v_first = v_angles[0], v_last = v_angles[v_angles.size() - 1];
+ if (v_last != 90.0f) {
+ return false;
+ }
+
+ if (v_first == 0.0f) {
+ /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
+ * full 180° range. */
+ vector<float> new_v_angles;
+ int hnum = h_angles.size();
+ int vnum = v_angles.size();
+ new_v_angles.reserve(2 * vnum - 1);
+ for (int i = vnum - 1; i > 0; i--) {
+ new_v_angles.push_back(90.0f - v_angles[i]);
+ }
+ for (int i = 0; i < vnum; i++) {
+ new_v_angles.push_back(90.0f + v_angles[i]);
+ }
+ for (int i = 0; i < hnum; i++) {
+ vector<float> new_intensity;
+ new_intensity.reserve(2 * vnum - 1);
+ for (int j = vnum - 2; j >= 0; j--) {
+ new_intensity.push_back(intensity[i][j]);
+ }
+ new_intensity.insert(new_intensity.end(), intensity[i].begin(), intensity[i].end());
+ intensity[i].swap(new_intensity);
+ }
+ v_angles.swap(new_v_angles);
+ }
+ else if (v_first == -90.0f) {
+ /* We have full 180° coverage, so just shift to match the angle range convention. */
+ for (int i = 0; i < v_angles.size(); i++) {
+ v_angles[i] += 90.0f;
+ }
+ }
+
+ return true;
}
bool IESFile::process_type_c()
{
- if(h_angles[0] == 90.0f) {
- /* Some files are stored from 90° to 270°, so we just rotate them to the regular 0°-180° range here. */
- for(int i = 0; i < h_angles.size(); i++) {
- h_angles[i] -= 90.0f;
- }
- }
-
- if(h_angles[0] != 0.0f) {
- return false;
- }
-
- if(h_angles.size() == 1) {
- h_angles.push_back(360.0f);
- intensity.push_back(intensity[0]);
- }
-
- if(h_angles[h_angles.size()-1] == 90.0f) {
- /* Only one quadrant is defined, so we need to mirror twice (from one to two, then to four).
- * Since the two->four mirroring step might also be required if we get an input of two quadrants,
- * we only do the first mirror here and later do the second mirror in either case. */
- int hnum = h_angles.size();
- for(int i = hnum-2; i >= 0; i--) {
- h_angles.push_back(180.0f - h_angles[i]);
- intensity.push_back(intensity[i]);
- }
- }
-
- if(h_angles[h_angles.size()-1] == 180.0f) {
- /* Mirror half to the full range. */
- int hnum = h_angles.size();
- for(int i = hnum-2; i >= 0; i--) {
- h_angles.push_back(360.0f - h_angles[i]);
- intensity.push_back(intensity[i]);
- }
- }
-
- /* Some files skip the 360° entry (contrary to standard) because it's supposed to be identical to the 0° entry.
- * If the file has a discernible order in its spacing, just fix this. */
- if(h_angles[h_angles.size()-1] != 360.0f) {
- int hnum = h_angles.size();
- float last_step = h_angles[hnum-1]-h_angles[hnum-2];
- float first_step = h_angles[1]-h_angles[0];
- float difference = 360.0f - h_angles[hnum-1];
- if(last_step == difference || first_step == difference) {
- h_angles.push_back(360.0f);
- intensity.push_back(intensity[0]);
- }
- else {
- return false;
- }
- }
-
- float v_first = v_angles[0], v_last = v_angles[v_angles.size()-1];
- if(v_first == 90.0f) {
- if(v_last == 180.0f) {
- /* Flip to ensure that vertical angles always start at 0°. */
- for(int i = 0; i < v_angles.size(); i++) {
- v_angles[i] = 180.0f - v_angles[i];
- }
- }
- else {
- return false;
- }
- }
- else if(v_first != 0.0f) {
- return false;
- }
-
- return true;
+ if (h_angles[0] == 90.0f) {
+ /* Some files are stored from 90° to 270°, so we just rotate them to the regular 0°-180° range here. */
+ for (int i = 0; i < h_angles.size(); i++) {
+ h_angles[i] -= 90.0f;
+ }
+ }
+
+ if (h_angles[0] != 0.0f) {
+ return false;
+ }
+
+ if (h_angles.size() == 1) {
+ h_angles.push_back(360.0f);
+ intensity.push_back(intensity[0]);
+ }
+
+ if (h_angles[h_angles.size() - 1] == 90.0f) {
+ /* Only one quadrant is defined, so we need to mirror twice (from one to two, then to four).
+ * Since the two->four mirroring step might also be required if we get an input of two quadrants,
+ * we only do the first mirror here and later do the second mirror in either case. */
+ int hnum = h_angles.size();
+ for (int i = hnum - 2; i >= 0; i--) {
+ h_angles.push_back(180.0f - h_angles[i]);
+ intensity.push_back(intensity[i]);
+ }
+ }
+
+ if (h_angles[h_angles.size() - 1] == 180.0f) {
+ /* Mirror half to the full range. */
+ int hnum = h_angles.size();
+ for (int i = hnum - 2; i >= 0; i--) {
+ h_angles.push_back(360.0f - h_angles[i]);
+ intensity.push_back(intensity[i]);
+ }
+ }
+
+ /* Some files skip the 360° entry (contrary to standard) because it's supposed to be identical to the 0° entry.
+ * If the file has a discernible order in its spacing, just fix this. */
+ if (h_angles[h_angles.size() - 1] != 360.0f) {
+ int hnum = h_angles.size();
+ float last_step = h_angles[hnum - 1] - h_angles[hnum - 2];
+ float first_step = h_angles[1] - h_angles[0];
+ float difference = 360.0f - h_angles[hnum - 1];
+ if (last_step == difference || first_step == difference) {
+ h_angles.push_back(360.0f);
+ intensity.push_back(intensity[0]);
+ }
+ else {
+ return false;
+ }
+ }
+
+ float v_first = v_angles[0], v_last = v_angles[v_angles.size() - 1];
+ if (v_first == 90.0f) {
+ if (v_last == 180.0f) {
+ /* Flip to ensure that vertical angles always start at 0°. */
+ for (int i = 0; i < v_angles.size(); i++) {
+ v_angles[i] = 180.0f - v_angles[i];
+ }
+ }
+ else {
+ return false;
+ }
+ }
+ else if (v_first != 0.0f) {
+ return false;
+ }
+
+ return true;
}
bool IESFile::process()
{
- if(h_angles.size() == 0 || v_angles.size() == 0) {
- return false;
- }
-
- if(type == TYPE_B) {
- if(!process_type_b()) {
- return false;
- }
- }
- else {
- assert(type == TYPE_C);
- if(!process_type_c()) {
- return false;
- }
- }
-
- assert(v_angles[0] == 0.0f);
- assert(h_angles[0] == 0.0f);
- assert(h_angles[h_angles.size()-1] == 360.0f);
-
- /* Convert from deg to rad. */
- for(int i = 0; i < v_angles.size(); i++) {
- v_angles[i] *= M_PI_F / 180.f;
- }
- for(int i = 0; i < h_angles.size(); i++) {
- h_angles[i] *= M_PI_F / 180.f;
- }
-
- return true;
+ if (h_angles.size() == 0 || v_angles.size() == 0) {
+ return false;
+ }
+
+ if (type == TYPE_B) {
+ if (!process_type_b()) {
+ return false;
+ }
+ }
+ else {
+ assert(type == TYPE_C);
+ if (!process_type_c()) {
+ return false;
+ }
+ }
+
+ assert(v_angles[0] == 0.0f);
+ assert(h_angles[0] == 0.0f);
+ assert(h_angles[h_angles.size() - 1] == 360.0f);
+
+ /* Convert from deg to rad. */
+ for (int i = 0; i < v_angles.size(); i++) {
+ v_angles[i] *= M_PI_F / 180.f;
+ }
+ for (int i = 0; i < h_angles.size(); i++) {
+ h_angles[i] *= M_PI_F / 180.f;
+ }
+
+ return true;
}
IESFile::~IESFile()
{
- clear();
+ clear();
}
CCL_NAMESPACE_END