mitsuba/include/mitsuba/core/frame.h

189 lines
5.7 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_CORE_FRAME_H_)
#define __MITSUBA_CORE_FRAME_H_
#include <mitsuba/mitsuba.h>
MTS_NAMESPACE_BEGIN
/**
* \brief Stores a three-dimensional orthonormal coordinate frame
*
* This class is mostly used to quickly convert between different
* cartesian coordinate systems and to efficiently compute certain
* quantities (e.g. \ref cosTheta(), \ref tanTheta, ..).
*
* \ingroup libcore
* \ingroup libpython
*/
struct Frame {
Vector s, t;
Normal n;
/// Default constructor -- performs no initialization!
inline Frame() { }
/// Given a normal and tangent vectors, construct a new coordinate frame
inline Frame(const Vector &s, const Vector &t, const Normal &n)
: s(s), t(t), n(n) {
}
/// Construct a frame from the given orthonormal vectors
inline Frame(const Vector &x, const Vector &y, const Vector &z)
: s(x), t(y), n(z) {
}
/// Construct a new coordinate frame from a single vector
inline Frame(const Vector &n) : n(n) {
coordinateSystem(n, s, t);
}
/// Unserialize from a binary data stream
inline Frame(Stream *stream) {
s = Vector(stream);
t = Vector(stream);
n = Normal(stream);
}
/// Serialize to a binary data stream
inline void serialize(Stream *stream) const {
s.serialize(stream);
t.serialize(stream);
n.serialize(stream);
}
/// Convert from world coordinates to local coordinates
inline Vector toLocal(const Vector &v) const {
return Vector(
dot(v, s),
dot(v, t),
dot(v, n)
);
}
/// Convert from local coordinates to world coordinates
inline Vector toWorld(const Vector &v) const {
return s * v.x + t * v.y + n * v.z;
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the squared cosine of the angle between the normal and v */
inline static Float cosTheta2(const Vector &v) {
return v.z * v.z;
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the cosine of the angle between the normal and v */
inline static Float cosTheta(const Vector &v) {
return v.z;
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the squared sine of the angle between the normal and v */
inline static Float sinTheta2(const Vector &v) {
return 1.0f - v.z * v.z;
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the sine of the angle between the normal and v */
inline static Float sinTheta(const Vector &v) {
Float temp = sinTheta2(v);
if (temp <= 0.0f)
return 0.0f;
return std::sqrt(temp);
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the tangent of the angle between the normal and v */
inline static Float tanTheta(const Vector &v) {
Float temp = 1 - v.z*v.z;
if (temp <= 0.0f)
return 0.0f;
return std::sqrt(temp) / v.z;
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the squared tangent of the angle between the normal and v */
inline static Float tanTheta2(const Vector &v) {
Float temp = 1 - v.z*v.z;
if (temp <= 0.0f)
return 0.0f;
return temp / (v.z * v.z);
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the sine of the phi parameter in spherical coordinates */
inline static Float sinPhi(const Vector &v) {
Float sinTheta = Frame::sinTheta(v);
if (sinTheta == 0.0f)
return 1.0f;
return math::clamp(v.y / sinTheta, (Float) -1.0f, (Float) 1.0f);
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the cosine of the phi parameter in spherical coordinates */
inline static Float cosPhi(const Vector &v) {
Float sinTheta = Frame::sinTheta(v);
if (sinTheta == 0.0f)
return 1.0f;
return math::clamp(v.x / sinTheta, (Float) -1.0f, (Float) 1.0f);
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the squared sine of the phi parameter in spherical
* coordinates */
inline static Float sinPhi2(const Vector &v) {
return math::clamp(v.y * v.y / sinTheta2(v), (Float) 0.0f, (Float) 1.0f);
}
/** \brief Assuming that the given direction is in the local coordinate
* system, return the squared cosine of the phi parameter in spherical
* coordinates */
inline static Float cosPhi2(const Vector &v) {
return math::clamp(v.x * v.x / sinTheta2(v), (Float) 0.0f, (Float) 1.0f);
}
/// Equality test
inline bool operator==(const Frame &frame) const {
return frame.s == s && frame.t == t && frame.n == n;
}
/// Inequality test
inline bool operator!=(const Frame &frame) const {
return !operator==(frame);
}
/// Return a string representation of this frame
inline std::string toString() const {
std::ostringstream oss;
oss << "Frame[" << std::endl
<< " s = " << s.toString() << "," << std::endl
<< " t = " << t.toString() << "," << std::endl
<< " n = " << n.toString() << std::endl
<< "]";
return oss.str();
}
};
MTS_NAMESPACE_END
#endif /* __MITSUBA_CORE_FRAME_H_ */