00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LUX_SPECTRUM_H
00024 #define LUX_SPECTRUM_H
00025
00026 #include "lux.h"
00027 #include "spd.h"
00028 #include "color.h"
00029
00030 namespace lux
00031 {
00032
00033 #define WAVELENGTH_SAMPLES 8
00034 #define WAVELENGTH_START 380.
00035 #define WAVELENGTH_END 720.
00036 static const float inv_WAVELENGTH_SAMPLES = 1.f / WAVELENGTH_SAMPLES;
00037
00038
00039
00040
00041 #ifndef DISABLED_LUX_USE_SSE
00042
00043 class Spectrum {
00044 friend class boost::serialization::access;
00045 public:
00046
00047 Spectrum(float v = 0.f) {
00048 for (int i = 0; i < COLOR_SAMPLES; ++i)
00049 c[i] = v;
00050 }
00051
00052 Spectrum(const float cs[COLOR_SAMPLES]) {
00053 for (int i = 0; i < COLOR_SAMPLES; ++i)
00054 c[i] = cs[i];
00055 }
00056 friend ostream &operator<<(ostream &, const Spectrum &);
00057 Spectrum &operator+=(const Spectrum &s2) {
00058 for (int i = 0; i < COLOR_SAMPLES; ++i)
00059 c[i] += s2.c[i];
00060 return *this;
00061 }
00062 Spectrum &operator-=(const Spectrum &s2) {
00063 for (int i = 0; i < COLOR_SAMPLES; ++i)
00064 c[i] -= s2.c[i];
00065 return *this;
00066 }
00067 Spectrum operator+(const Spectrum &s2) const {
00068 Spectrum ret = *this;
00069 for (int i = 0; i < COLOR_SAMPLES; ++i)
00070 ret.c[i] += s2.c[i];
00071 return ret;
00072 }
00073 Spectrum operator-(const Spectrum &s2) const {
00074 Spectrum ret = *this;
00075 for (int i = 0; i < COLOR_SAMPLES; ++i)
00076 ret.c[i] -= s2.c[i];
00077 return ret;
00078 }
00079 Spectrum operator/(const Spectrum &s2) const {
00080 Spectrum ret = *this;
00081 for (int i = 0; i < COLOR_SAMPLES; ++i)
00082 ret.c[i] /= s2.c[i];
00083 return ret;
00084 }
00085 Spectrum operator*(const Spectrum &sp) const {
00086 Spectrum ret = *this;
00087 for (int i = 0; i < COLOR_SAMPLES; ++i)
00088 ret.c[i] *= sp.c[i];
00089 return ret;
00090 }
00091 Spectrum &operator*=(const Spectrum &sp) {
00092 for (int i = 0; i < COLOR_SAMPLES; ++i)
00093 c[i] *= sp.c[i];
00094 return *this;
00095 }
00096 Spectrum operator*(float a) const {
00097 Spectrum ret = *this;
00098 for (int i = 0; i < COLOR_SAMPLES; ++i)
00099 ret.c[i] *= a;
00100 return ret;
00101 }
00102 Spectrum &operator*=(float a) {
00103 for (int i = 0; i < COLOR_SAMPLES; ++i)
00104 c[i] *= a;
00105 return *this;
00106 }
00107 friend inline
00108 Spectrum operator*(float a, const Spectrum &s) {
00109 return s * a;
00110 }
00111 Spectrum operator/(float a) const {
00112 return *this * (1.f / a);
00113 }
00114 Spectrum &operator/=(float a) {
00115 float inv = 1.f / a;
00116 for (int i = 0; i < COLOR_SAMPLES; ++i)
00117 c[i] *= inv;
00118 return *this;
00119 }
00120 void AddWeighted(float w, const Spectrum &s) {
00121 for (int i = 0; i < COLOR_SAMPLES; ++i)
00122 c[i] += w * s.c[i];
00123 }
00124 bool operator==(const Spectrum &sp) const {
00125 for (int i = 0; i < COLOR_SAMPLES; ++i)
00126 if (c[i] != sp.c[i]) return false;
00127 return true;
00128 }
00129 bool operator!=(const Spectrum &sp) const {
00130 return !(*this == sp);
00131 }
00132 bool Black() const {
00133 for (int i = 0; i < COLOR_SAMPLES; ++i)
00134 if (c[i] != 0.) return false;
00135 return true;
00136 }
00137 Spectrum Sqrt() const {
00138 Spectrum ret;
00139 for (int i = 0; i < COLOR_SAMPLES; ++i)
00140 ret.c[i] = sqrtf(c[i]);
00141 return ret;
00142 }
00143 Spectrum Pow(const Spectrum &e) const {
00144 Spectrum ret;
00145 for (int i = 0; i < COLOR_SAMPLES; ++i)
00146 ret.c[i] = c[i] > 0 ? powf(c[i], e.c[i]) : 0.f;
00147 return ret;
00148 }
00149 Spectrum Pow(const float e) const {
00150 Spectrum ret;
00151 for (int i = 0; i < COLOR_SAMPLES; ++i)
00152 ret.c[i] = c[i] > 0 ? powf(c[i], e) : 0.f;
00153 return ret;
00154 }
00155 Spectrum operator-() const {
00156 Spectrum ret;
00157 for (int i = 0; i < COLOR_SAMPLES; ++i)
00158 ret.c[i] = -c[i];
00159 return ret;
00160 }
00161 friend Spectrum Exp(const Spectrum &s) {
00162 Spectrum ret;
00163 for (int i = 0; i < COLOR_SAMPLES; ++i)
00164 ret.c[i] = expf(s.c[i]);
00165 return ret;
00166 }
00167 Spectrum Clamp(float low = 0.f,
00168 float high = INFINITY) const {
00169 Spectrum ret;
00170 for (int i = 0; i < COLOR_SAMPLES; ++i)
00171 ret.c[i] = ::Clamp(c[i], low, high);
00172 return ret;
00173 }
00174 bool IsNaN() const {
00175 for (int i = 0; i < COLOR_SAMPLES; ++i)
00176 if (isnan(c[i])) return true;
00177 return false;
00178 }
00179 void Print(FILE *f) const {
00180 for (int i = 0; i < COLOR_SAMPLES; ++i)
00181 fprintf(f, "%f ", c[i]);
00182 }
00183 XYZColor ToXYZ() const {
00184 float xyz[3];
00185 xyz[0] = xyz[1] = xyz[2] = 0.;
00186 for (int i = 0; i < COLOR_SAMPLES; ++i) {
00187 xyz[0] += XWeight[i] * c[i];
00188 xyz[1] += YWeight[i] * c[i];
00189 xyz[2] += ZWeight[i] * c[i];
00190 }
00191 return XYZColor(xyz);
00192 }
00193 float y() const {
00194 float v = 0.;
00195 for (int i = 0; i < COLOR_SAMPLES; ++i)
00196 v += YWeight[i] * c[i];
00197 return v;
00198 }
00199 bool operator<(const Spectrum &s2) const {
00200 return y() < s2.y();
00201 }
00202 friend class lux::ParamSet;
00203
00204
00205 float c[COLOR_SAMPLES];
00206
00207 protected:
00208
00209 static float XWeight[COLOR_SAMPLES];
00210 static float YWeight[COLOR_SAMPLES];
00211 static float ZWeight[COLOR_SAMPLES];
00212 friend Spectrum FromXYZ(float x, float y, float z);
00213
00214 private:
00215 template<class Archive>
00216 void serialize(Archive & ar, const unsigned int version)
00217 {
00218 for (int i = 0; i < COLOR_SAMPLES; ++i)
00219 ar & c[i];
00220 }
00221 };
00222
00223 #else //LUX_USE_SSE
00224
00225 #define COLOR_VECTORS 1
00226
00227 class _MM_ALIGN16 Spectrum {
00228 public:
00229
00230 Spectrum(float v = 0.f) {
00231 for (int i = 0; i < COLOR_SAMPLES; ++i)
00232 c[i] = v;
00233 }
00234 Spectrum(float cs[COLOR_SAMPLES]) {
00235 for (int i = 0; i < COLOR_SAMPLES; ++i)
00236 c[i] = cs[i];
00237 }
00238 Spectrum(__m128 cv[COLOR_VECTORS])
00239 {
00240 for (int i = 0; i < COLOR_VECTORS; ++i)
00241 cvec[i]=cv[i];
00242 }
00243
00244 friend ostream &operator<<(ostream &, const Spectrum &);
00245 Spectrum &operator+=(const Spectrum &s2) {
00246 for (int i = 0; i < COLOR_SAMPLES; ++i)
00247 c[i] += s2.c[i];
00248 return *this;
00249 }
00250 Spectrum operator+(const Spectrum &s2) const {
00251 Spectrum ret;
00252 for (int i = 0; i < COLOR_VECTORS; ++i)
00253 ret.cvec[i]=_mm_add_ps(cvec[i],s2.cvec[i]);
00254
00255
00256
00257 return ret;
00258 }
00259 Spectrum operator-(const Spectrum &s2) const {
00260 Spectrum ret = *this;
00261 for (int i = 0; i < COLOR_SAMPLES; ++i)
00262 ret.c[i] -= s2.c[i];
00263 return ret;
00264 }
00265 Spectrum operator/(const Spectrum &s2) const {
00266 Spectrum ret;
00267 for (int i = 0; i < COLOR_VECTORS; ++i)
00268 ret.cvec[i]=_mm_div_ps(cvec[i],s2.cvec[i]);
00269
00270
00271 return ret;
00272 }
00273 Spectrum operator*(const Spectrum &sp) const {
00274 Spectrum ret;
00275 for (int i = 0; i < COLOR_VECTORS; ++i)
00276 ret.cvec[i]=_mm_mul_ps(cvec[i],sp.cvec[i]);
00277
00278
00279
00280 return ret;
00281 }
00282 Spectrum &operator*=(const Spectrum &sp) {
00283
00284
00285
00286 for (int i = 0; i < COLOR_VECTORS; ++i)
00287 cvec[i]=_mm_mul_ps(cvec[i],sp.cvec[i]);
00288
00289 return *this;
00290 }
00291 Spectrum operator*(float a) const {
00292 Spectrum ret = *this;
00293 for (int i = 0; i < COLOR_SAMPLES; ++i)
00294 ret.c[i] *= a;
00295 return ret;
00296 }
00297 Spectrum &operator*=(float a) {
00298 for (int i = 0; i < COLOR_SAMPLES; ++i)
00299 c[i] *= a;
00300 return *this;
00301 }
00302 friend inline
00303 Spectrum operator*(float a, const Spectrum &s) {
00304 return s * a;
00305 }
00306 Spectrum operator/(float a) const {
00307 return *this * (1.f / a);
00308 }
00309 Spectrum &operator/=(float a) {
00310 float inv = 1.f / a;
00311 for (int i = 0; i < COLOR_SAMPLES; ++i)
00312 c[i] *= inv;
00313 return *this;
00314 }
00315 void AddWeighted(float w, const Spectrum &s) {
00316
00317
00318 __m128 wvec=_mm_set_ps1(w);
00319
00320 for (int i = 0; i < COLOR_VECTORS; ++i)
00321 cvec[i]=_mm_add_ps(cvec[i],_mm_mul_ps(s.cvec[i],wvec));
00322 }
00323 bool operator==(const Spectrum &sp) const {
00324 for (int i = 0; i < COLOR_SAMPLES; ++i)
00325 if (c[i] != sp.c[i]) return false;
00326
00327
00328
00329 return true;
00330 }
00331 bool operator!=(const Spectrum &sp) const {
00332 return !(*this == sp);
00333 }
00334 bool Black() const {
00335 for (int i = 0; i < COLOR_SAMPLES; ++i)
00336 if (c[i] != 0.) return false;
00337 return true;
00338 }
00339 Spectrum Sqrt() const {
00340 Spectrum ret;
00341
00342
00343
00344 for (int i = 0; i < COLOR_VECTORS; ++i)
00345 ret.cvec[i]=_mm_sqrt_ps(cvec[i]);
00346 return ret;
00347 }
00348 Spectrum Pow(const Spectrum &e) const {
00349 Spectrum ret;
00350 for (int i = 0; i < COLOR_SAMPLES; ++i)
00351 ret.c[i] = c[i] > 0 ? powf(c[i], e.c[i]) : 0.f;
00352 return ret;
00353 }
00354 Spectrum operator-() const {
00355 Spectrum ret;
00356 for (int i = 0; i < COLOR_SAMPLES; ++i)
00357 ret.c[i] = -c[i];
00358 return ret;
00359 }
00360 friend Spectrum Exp(const Spectrum &s) {
00361 Spectrum ret;
00362 for (int i = 0; i < COLOR_SAMPLES; ++i)
00363 ret.c[i] = expf(s.c[i]);
00364 return ret;
00365 }
00366 Spectrum Clamp(float low = 0.f,
00367 float high = INFINITY) const {
00368 Spectrum ret;
00369 for (int i = 0; i < COLOR_SAMPLES; ++i)
00370 ret.c[i] = ::Clamp(c[i], low, high);
00371 return ret;
00372 }
00373 bool IsNaN() const {
00374 for (int i = 0; i < COLOR_SAMPLES; ++i)
00375 if (isnan(c[i])) return true;
00376 return false;
00377 }
00378 void Print(FILE *f) const {
00379 for (int i = 0; i < COLOR_SAMPLES; ++i)
00380 fprintf(f, "%f ", c[i]);
00381 }
00382 void XYZ(float xyz[3]) const {
00383 xyz[0] = xyz[1] = xyz[2] = 0.;
00384 for (int i = 0; i < COLOR_SAMPLES; ++i) {
00385 xyz[0] += XWeight[i] * c[i];
00386 xyz[1] += YWeight[i] * c[i];
00387 xyz[2] += ZWeight[i] * c[i];
00388 }
00389 }
00390 float y() const {
00391 float v = 0.;
00392 for (int i = 0; i < COLOR_SAMPLES; ++i)
00393 v += YWeight[i] * c[i];
00394 return v;
00395 }
00396 bool operator<(const Spectrum &s2) const {
00397 return y() < s2.y();
00398 }
00399 friend class ParamSet;
00400
00401
00402
00403
00404 union
00405 {
00406 __m128 cvec[COLOR_VECTORS];
00407 float c[COLOR_SAMPLES];
00408 };
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 protected:
00419
00420 static float XWeight[COLOR_SAMPLES];
00421 static float YWeight[COLOR_SAMPLES];
00422 static float ZWeight[COLOR_SAMPLES];
00423 friend Spectrum FromXYZ(float x, float y, float z);
00424 };
00425
00426 #endif
00427
00428 Spectrum FromXYZ(float x, float y, float z);
00429
00430 #define Scalar float
00431
00432 class SWCSpectrum {
00433 friend class boost::serialization::access;
00434 public:
00435
00436 SWCSpectrum(Scalar v = 0.f) {
00437 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00438 c[i] = v;
00439 }
00440 SWCSpectrum(Spectrum s);
00441
00442 SWCSpectrum(const SPD *s);
00443
00444 SWCSpectrum(float cs[WAVELENGTH_SAMPLES]) {
00445 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00446 c[i] = cs[i];
00447 }
00448 friend ostream &operator<<(ostream &, const SWCSpectrum &);
00449 SWCSpectrum &operator+=(const SWCSpectrum &s2) {
00450 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00451 c[i] += s2.c[i];
00452 return *this;
00453 }
00454 SWCSpectrum operator+(const SWCSpectrum &s2) const {
00455 SWCSpectrum ret = *this;
00456 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00457 ret.c[i] += s2.c[i];
00458 return ret;
00459 }
00460 SWCSpectrum operator-(const SWCSpectrum &s2) const {
00461 SWCSpectrum ret = *this;
00462 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00463 ret.c[i] -= s2.c[i];
00464 return ret;
00465 }
00466 SWCSpectrum operator/(const SWCSpectrum &s2) const {
00467 SWCSpectrum ret = *this;
00468 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00469 ret.c[i] /= s2.c[i];
00470 return ret;
00471 }
00472 SWCSpectrum operator*(const SWCSpectrum &sp) const {
00473 SWCSpectrum ret = *this;
00474 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00475 ret.c[i] *= sp.c[i];
00476 return ret;
00477 }
00478 SWCSpectrum &operator*=(const SWCSpectrum &sp) {
00479 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00480 c[i] *= sp.c[i];
00481 return *this;
00482 }
00483 SWCSpectrum operator*(Scalar a) const {
00484 SWCSpectrum ret = *this;
00485 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00486 ret.c[i] *= a;
00487 return ret;
00488 }
00489 SWCSpectrum &operator*=(Scalar a) {
00490 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00491 c[i] *= a;
00492 return *this;
00493 }
00494 friend inline
00495 SWCSpectrum operator*(Scalar a, const SWCSpectrum &s) {
00496 return s * a;
00497 }
00498 SWCSpectrum operator/(Scalar a) const {
00499 return *this * (1.f / a);
00500 }
00501 SWCSpectrum &operator/=(Scalar a) {
00502 Scalar inv = 1.f / a;
00503 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00504 c[i] *= inv;
00505 return *this;
00506 }
00507 void AddWeighted(Scalar w, const SWCSpectrum &s) {
00508 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00509 c[i] += w * s.c[i];
00510 }
00511 bool operator==(const SWCSpectrum &sp) const {
00512 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00513 if (c[i] != sp.c[i]) return false;
00514 return true;
00515 }
00516 bool operator!=(const SWCSpectrum &sp) const {
00517 return !(*this == sp);
00518 }
00519 bool Black() const {
00520 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00521 if (c[i] != 0.f) return false;
00522 return true;
00523 }
00524 SWCSpectrum Sqrt() const {
00525 SWCSpectrum ret;
00526 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00527 ret.c[i] = sqrtf(c[i]);
00528 return ret;
00529 }
00530 SWCSpectrum Pow(const SWCSpectrum &e) const {
00531 SWCSpectrum ret;
00532 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00533 ret.c[i] = c[i] > 0 ? powf(c[i], e.c[i]) : 0.f;
00534 return ret;
00535 }
00536 SWCSpectrum operator-() const {
00537 SWCSpectrum ret;
00538 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00539 ret.c[i] = -c[i];
00540 return ret;
00541 }
00542 friend SWCSpectrum Exp(const SWCSpectrum &s) {
00543 SWCSpectrum ret;
00544 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00545 ret.c[i] = expf(s.c[i]);
00546 return ret;
00547 }
00548 SWCSpectrum Clamp(Scalar low = 0.f,
00549 Scalar high = INFINITY) const {
00550 SWCSpectrum ret;
00551 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00552 ret.c[i] = ::Clamp(c[i], low, high);
00553 return ret;
00554 }
00555 bool IsNaN() const {
00556 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00557 if (isnan(c[i])) return true;
00558 return false;
00559 }
00560 void Print(FILE *f) const {
00561 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00562 fprintf(f, "%f ", c[i]);
00563 }
00564 XYZColor ToXYZ() const;
00565 Scalar y() const;
00566 Scalar filter() const;
00567
00568 bool operator<(const SWCSpectrum &s2) const {
00569 return y() < s2.y();
00570 }
00571 friend class lux::ParamSet;
00572
00573
00574 Scalar c[WAVELENGTH_SAMPLES];
00575
00576 private:
00577 template<class Archive>
00578 void serialize(Archive & ar, const unsigned int version)
00579 {
00580 for (int i = 0; i < WAVELENGTH_SAMPLES; ++i)
00581 ar & c[i];
00582 }
00583 };
00584
00585 }
00586
00587 #endif // LUX_SPECTRUM_H