/* This file is part of Mitsuba, a physically based rendering system. Copyright (c) 2007-2012 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 . */ #include #include #include #include MTS_NAMESPACE_BEGIN /*!\plugin{fluencemeter}{Fluence meter} * \order{7} * \parameters{ * \parameter{toWorld}{\Transform\Or\Animation}{ * Specifies an optional sensor-to-world transformation. * \default{none (i.e. sensor space $=$ world space)} * } * \parameter{shutterOpen, shutterClose}{\Float}{ * Specifies the time interval of the measurement---this * is only relevant when the scene is in motion. * \default{0} * } * } * * This sensor plugin implements a simple fluence meter, which measures * the average radiance passing through a specified position. * By default, the sensor is located at the origin. * * Such a sensor is useful for conducting virtual experiments and * testing the renderer for correctness. * * \vspace{4mm} * \begin{xml} * * * * * * * * * * * * * * * * * * * \end{xml} */ class FluenceMeter : public Sensor { public: FluenceMeter(const Properties &props) : Sensor(props) { m_type |= EDeltaPosition; if (props.getTransform("toWorld", Transform()).hasScale()) Log(EError, "Scale factors in the sensor-to-world " "transformation are not allowed!"); } FluenceMeter(Stream *stream, InstanceManager *manager) : Sensor(stream, manager) { configure(); } Spectrum sampleRay(Ray &ray, const Point2 &pixelSample, const Point2 &otherSample, Float timeSample) const { ray.time = sampleTime(timeSample); ray.mint = Epsilon; ray.maxt = std::numeric_limits::infinity(); const Transform &trafo = m_worldTransform->eval(ray.time); ray.setOrigin(trafo(Point(0.0f))); ray.setDirection(trafo(Warp::squareToUniformSphere(pixelSample))); return Spectrum(1.0f); } Spectrum samplePosition(PositionSamplingRecord &pRec, const Point2 &sample, const Point2 *extra) const { const Transform &trafo = m_worldTransform->eval(pRec.time); pRec.p = trafo(Point(0.0f)); pRec.n = Normal(0.0f); pRec.pdf = 1.0f; pRec.measure = EDiscrete; return Spectrum(1.0f); } Spectrum evalPosition(const PositionSamplingRecord &pRec) const { return Spectrum((pRec.measure == EDiscrete) ? 1.0f : 0.0f); } Float pdfPosition(const PositionSamplingRecord &pRec) const { return (pRec.measure == EDiscrete) ? 1.0f : 0.0f; } Spectrum sampleDirection(DirectionSamplingRecord &dRec, PositionSamplingRecord &pRec, const Point2 &sample, const Point2 *extra) const { dRec.d = Warp::squareToUniformSphere(sample); dRec.pdf = INV_FOURPI; dRec.measure = ESolidAngle; return Spectrum(1.0f); } Float pdfDirection(const DirectionSamplingRecord &dRec, const PositionSamplingRecord &pRec) const { return (dRec.measure == ESolidAngle) ? INV_FOURPI : 0.0f; } Spectrum evalDirection(const DirectionSamplingRecord &dRec, const PositionSamplingRecord &pRec) const { return Spectrum((dRec.measure == ESolidAngle) ? INV_FOURPI : 0.0f); } Spectrum sampleDirect(DirectSamplingRecord &dRec, const Point2 &sample) const { const Transform &trafo = m_worldTransform->eval(dRec.time); dRec.p = trafo.transformAffine(Point(0.0f)); dRec.pdf = 1.0f; dRec.measure = EDiscrete; dRec.uv = Point2(0.5f); dRec.d = dRec.p - dRec.ref; dRec.dist = dRec.d.length(); Float invDist = 1.0f / dRec.dist; dRec.d *= invDist; dRec.n = Normal(0.0f); dRec.pdf = 1; dRec.measure = EDiscrete; return Spectrum(INV_FOURPI * invDist * invDist); } Float pdfDirect(const DirectSamplingRecord &dRec) const { return dRec.measure == EDiscrete ? 1.0f : 0.0f; } AABB getAABB() const { return m_worldTransform->getTranslationBounds(); } std::string toString() const { std::ostringstream oss; oss << "FluenceMeter[" << endl << " worldTransform = " << indent(m_worldTransform.toString()) << "," << endl << " sampler = " << indent(m_sampler->toString()) << "," << endl << " film = " << indent(m_film->toString()) << "," << endl << " medium = " << indent(m_medium.toString()) << "," << endl << " shutterOpen = " << m_shutterOpen << "," << endl << " shutterOpenTime = " << m_shutterOpenTime << endl << "]"; return oss.str(); } MTS_DECLARE_CLASS() }; MTS_IMPLEMENT_CLASS_S(FluenceMeter, false, Sensor) MTS_EXPORT_PLUGIN(FluenceMeter, "Fluence meter"); MTS_NAMESPACE_END