2011-03-14 21:58:58 +08:00
|
|
|
/*
|
|
|
|
This file is part of Mitsuba, a physically based rendering system.
|
|
|
|
|
2011-04-14 21:15:59 +08:00
|
|
|
Copyright (c) 2007-2011 by Wenzel Jakob and others.
|
2011-03-14 21:58:58 +08:00
|
|
|
|
|
|
|
Mitsuba is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License Version 3
|
|
|
|
as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
Mitsuba is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2011-04-14 21:15:59 +08:00
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2011-03-14 21:58:58 +08:00
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <mitsuba/render/photon.h>
|
|
|
|
|
|
|
|
MTS_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
/* Precompute cosine/sine values for quick conversions
|
|
|
|
from quantized spherical coordinates to floating
|
|
|
|
point vectors. */
|
|
|
|
Float Photon::m_cosTheta[256];
|
|
|
|
Float Photon::m_sinTheta[256];
|
|
|
|
Float Photon::m_cosPhi[256];
|
|
|
|
Float Photon::m_sinPhi[256];
|
|
|
|
Float Photon::m_expTable[256];
|
|
|
|
|
|
|
|
bool Photon::m_precompTableReady = Photon::createPrecompTables();
|
|
|
|
|
|
|
|
bool Photon::createPrecompTables() {
|
|
|
|
for (int i=0; i<256; i++) {
|
|
|
|
Float angle = (Float) i * ((Float) M_PI / 256.0f);
|
|
|
|
m_cosPhi[i] = std::cos(2.0f * angle);
|
|
|
|
m_sinPhi[i] = std::sin(2.0f * angle);
|
|
|
|
m_cosTheta[i] = std::cos(angle);
|
|
|
|
m_sinTheta[i] = std::sin(angle);
|
|
|
|
m_expTable[i] = std::ldexp((Float) 1, i - (128+8));
|
|
|
|
}
|
|
|
|
m_expTable[0] = 0;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Photon::Photon(Stream *stream) {
|
|
|
|
stream->readSingleArray(pos, 3);
|
|
|
|
#if defined(DOUBLE_PRECISION) || SPECTRUM_SAMPLES > 3
|
|
|
|
power = Spectrum(stream);
|
|
|
|
phi = stream->readUChar();
|
|
|
|
theta = stream->readUChar();
|
|
|
|
phiN = stream->readUChar();
|
|
|
|
thetaN = stream->readUChar();
|
|
|
|
#else
|
|
|
|
stream->read(power, 8);
|
|
|
|
#endif
|
|
|
|
depth = stream->readUShort();
|
|
|
|
axis = stream->readUChar();
|
|
|
|
unused = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Photon::Photon(const Point &p, const Normal &normal,
|
2011-03-16 03:08:01 +08:00
|
|
|
const Vector &dir, const Spectrum &P,
|
|
|
|
uint16_t _depth) {
|
2011-03-14 21:58:58 +08:00
|
|
|
if (P.isNaN())
|
|
|
|
SLog(EWarn, "Creating an invalid photon with power: %s", P.toString().c_str());
|
|
|
|
|
|
|
|
/* Possibly convert to single precision floating point
|
|
|
|
(if Mitsuba is configured to use double precision) */
|
|
|
|
pos[0] = (float) p.x;
|
|
|
|
pos[1] = (float) p.y;
|
|
|
|
pos[2] = (float) p.z;
|
|
|
|
depth = _depth;
|
|
|
|
unused = 0;
|
|
|
|
axis = -1;
|
|
|
|
|
|
|
|
/* Convert the direction into an approximate spherical
|
|
|
|
coordinate format to reduce storage requirements */
|
|
|
|
theta = (uint8_t) std::min(255,
|
|
|
|
(int) (std::acos(dir.z) * (256.0 / M_PI)));
|
|
|
|
|
|
|
|
int tmp = std::min(255,
|
|
|
|
(int) (std::atan2(dir.y, dir.x) * (256.0 / (2.0 * M_PI))));
|
|
|
|
if (tmp < 0)
|
|
|
|
phi = (uint8_t) (tmp + 256);
|
|
|
|
else
|
|
|
|
phi = (uint8_t) tmp;
|
|
|
|
|
|
|
|
if (normal.isZero()) {
|
|
|
|
thetaN = phiN = 0;
|
|
|
|
} else {
|
|
|
|
thetaN = (uint8_t) std::min(255,
|
|
|
|
(int) (std::acos(normal.z) * (256.0 / M_PI)));
|
|
|
|
tmp = std::min(255,
|
|
|
|
(int) (std::atan2(normal.y, normal.x) * (256.0 / (2.0 * M_PI))));
|
|
|
|
if (tmp < 0)
|
|
|
|
phiN = (uint8_t) (tmp + 256);
|
|
|
|
else
|
|
|
|
phiN = (uint8_t) tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(DOUBLE_PRECISION) || SPECTRUM_SAMPLES > 3
|
|
|
|
power = P;
|
|
|
|
#else
|
|
|
|
/* Pack the photon power into Greg Ward's RGBE format */
|
|
|
|
P.toRGBE(power);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
MTS_NAMESPACE_END
|