189 lines
5.7 KiB
C++
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_ */
|