mitsuba/src/librender/photon.cpp

113 lines
3.1 KiB
C++
Raw Normal View History

2011-03-14 21:58:58 +08:00
/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2010 by Wenzel Jakob and others.
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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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