Photon::Photon(const Point &p, const Normal &normal, const Vector &dir, const Spectrum &P, uint16_t _depth) { if (!P.isValid()) 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) */ position = p; data.depth = _depth; flags = 0; /* Convert the direction into an approximate spherical coordinate format to reduce storage requirements */ data.theta = (uint8_t) std::min(255, (int) (math::safe_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) data.phi = (uint8_t) (tmp + 256); else data.phi = (uint8_t) tmp; if (normal.isZero()) { data.thetaN = data.phiN = 0; } else { data.thetaN = (uint8_t) std::min(255, (int) (math::safe_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) data.phiN = (uint8_t) (tmp + 256); else data.phiN = (uint8_t) tmp; } #if defined(SINGLE_PRECISION) && SPECTRUM_SAMPLES == 3 /* Pack the photon power into Greg Ward's RGBE format */ P.toRGBE(data.power); #else data.power = P; #endif }