Nori  23
photon.cpp
1 /*
2  This file is part of Nori, a simple educational ray tracer
3 
4  Copyright (c) 2015 by Wenzel Jakob
5 
6  Nori is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Nori is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <nori/photon.h>
20 
21 NORI_NAMESPACE_BEGIN
22 
23 bool PhotonData::m_precompTableReady = PhotonData::initialize();
24 float PhotonData::m_cosTheta[256];
25 float PhotonData::m_sinTheta[256];
26 float PhotonData::m_cosPhi[256];
27 float PhotonData::m_sinPhi[256];
28 float PhotonData::m_expTable[256];
29 
31  for (int i=0; i<256; i++) {
32  float angle = (float) i * ((float) M_PI / 256.0f);
33  m_cosPhi[i] = std::cos(2.0f * angle);
34  m_sinPhi[i] = std::sin(2.0f * angle);
35  m_cosTheta[i] = std::cos(angle);
36  m_sinTheta[i] = std::sin(angle);
37  m_expTable[i] = std::ldexp((float) 1, i - (128+8));
38  }
39  m_expTable[0] = 0;
40  return true;
41 }
42 
43 PhotonData::PhotonData(const Vector3f &dir, const Color3f &power) {
44  if (!power.isValid())
45  std::cerr << "Creating an invalid photon with power: " << power << endl;
46 
47  /* Convert the direction into an approximate spherical
48  coordinate format to reduce storage requirements */
49  theta = (uint8_t) std::min(255,
50  (int) (std::acos(dir.z()) * (256.0f / M_PI)));
51 
52  int tmp = std::min(255,
53  (int) (std::atan2(dir.y(), dir.x()) * (256.0f / (2.0f * M_PI))));
54  if (tmp < 0)
55  phi = (uint8_t) (tmp + 256);
56  else
57  phi = (uint8_t) tmp;
58 
59  /* Convert to Ward's RGBE format */
60  float max = power.maxCoeff();
61  if (max < 1e-32) {
62  rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
63  } else {
64  int e;
65  /* Extract exponent and convert the fractional part into
66  the [0..255] range. Afterwards, divide by max so that
67  any color component multiplied by the result will be in [0,255] */
68  max = std::frexp(max, &e) * 256.0f / max;
69  rgbe[0] = (uint8_t) (power.r() * max);
70  rgbe[1] = (uint8_t) (power.g() * max);
71  rgbe[2] = (uint8_t) (power.b() * max);
72  rgbe[3] = e + 128; /* Exponent value in bias format */
73  }
74 }
75 
76 NORI_NAMESPACE_END
Represents a linear RGB color value.
Definition: color.h:29
bool isValid() const
Check if the color vector contains a NaN/Inf/negative value.
Definition: common.cpp:224
float & g()
Return a reference to the green channel.
Definition: color.h:54
float & b()
Return a reference to the blue channel.
Definition: color.h:58
float & r()
Return a reference to the red channel.
Definition: color.h:50
uint8_t rgbe[4]
Photon power stored in Greg Ward's RGBE format.
Definition: photon.h:29
PhotonData()
Dummy constructor.
Definition: photon.h:34
uint8_t theta
Discretized photon direction (theta component)
Definition: photon.h:30
static bool initialize()
Initialize the precomputed lookup tables.
Definition: photon.cpp:30
uint8_t phi
Discretized photon direction (phi component)
Definition: photon.h:31