mitsuba/include/mitsuba/bidir/manifold.h

155 lines
4.0 KiB
C++

/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2014 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/>.
*/
#pragma once
#if !defined(__MITSUBA_BIDIR_MANIFOLD_H_)
#define __MITSUBA_BIDIR_MANIFOLD_H_
#include <mitsuba/bidir/vertex.h>
#define MTS_MANIFOLD_DEBUG 0
#define MTS_MANIFOLD_EPSILON Epsilon
#define MTS_MANIFOLD_MAX_ITERATIONS 20
MTS_NAMESPACE_BEGIN
/**
* \brief Utility class for perturbing paths located on a specular manifold.
* \author Wenzel Jakob
*/
class MTS_EXPORT_BIDIR SpecularManifold : public Object {
public:
/// Construct an unitialized specular manifold data structure
SpecularManifold(const Scene *scene, int maxIterations = -1);
/**
* \brief Initialize the specular manifold with the specified
* path segment
*/
bool init(const Path &path, int start, int end);
/**
* \brief Update the provided path segment based on the stored
* specular manifold configuration
*/
bool update(Path &path, int start, int end);
/// Attempt to move the movable endpoint vertex to position \c target
bool move(const Point &target, const Normal &normal);
/**
* \brief Compute the generalized geometric term between 'a' and 'b'
*/
Float G(const Path &path, int a, int b);
/**
* \brief Compute a product of standard and generalized geometric
* terms between 'a' and 'b' depending on whether vertices are
* specular or non-specular.
*/
Float multiG(const Path &path, int a, int b);
Float det(const Path &path, int a, int b, int c);
/// Return the number of iterations used by \ref move()
inline int getIterationCount() const { return m_iterations; }
/// Return the position of a vertex
inline const Point &getPosition(int i) { return m_vertices[i].p; }
/// Return a string representation
std::string toString() const;
MTS_DECLARE_CLASS()
protected:
/// Virtual destructor
virtual ~SpecularManifold() { }
private:
enum EType {
EPinnedPosition = 0,
EPinnedDirection,
EReflection,
ERefraction,
EMedium,
EMovable
};
/// Describes a single interaction on the path
struct SimpleVertex {
bool degenerate : 1;
EType type : 31;
/* Position and partials */
Point p;
Vector dpdu, dpdv;
/* Normal and partials */
Normal n, gn;
Vector dndu, dndv;
/* "Microfacet" normal */
Normal m;
/* Further information about the vertex */
Float eta;
const Object *object;
/* Scratch space for matrix assembly */
Matrix2x2 a, b, c, u;
/* Manifold tangent space projected onto this vertex */
Matrix2x2 Tp;
/// Initialize certain fields to zero by default
inline SimpleVertex(EType type, const Point &p) :
degenerate(false), type(type), p(p), dpdu(0.0f),
dpdv(0.0f), n(0.0f), dndu(0.0f), dndv(0.0f),
m(0.0f), eta(1.0f), object(NULL) { }
/// Map a tangent space displacement into world space
inline Vector map(Float u, Float v) const {
Vector2 T = Tp * Vector2(u, v);
return T.x * dpdu + T.y * dpdv;
}
std::string toString() const;
};
/// Take the specified step and project back onto the manifold
bool project(const Vector &d);
/**
* \brief Compute the tangent vectors with the specified
* components when projected onto the movable endpoint vertex
*/
bool computeTangents();
void check(SimpleVertex *v);
protected:
const Scene *m_scene;
Float m_time;
int m_iterations, m_maxIterations;
std::vector<SimpleVertex> m_vertices, m_proposal;
};
MTS_NAMESPACE_END
#endif /* __MITSUBA_BIDIR_MANIFOLD_H_ */