mitsuba/include/mitsuba/core/ray.h

272 lines
7.0 KiB
C++

/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2011 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/>.
*/
#if !defined(__RAY_H)
#define __RAY_H
#include <mitsuba/mitsuba.h>
MTS_NAMESPACE_BEGIN
/** \brief Simple three-dimensional ray data structure with
* minimum / maximum extent information.
*
* The somewhat peculiar ordering of the attributes is due
* to alignment purposes and should not be changed.
*
* \ingroup libcore
*/
struct Ray {
Point o; ///< Ray origin
Float mint; ///< Minimum range for intersection tests
Vector d; ///< Ray direction
Float maxt; ///< Maximum range for intersection tests
Vector dRcp; ///< Componentwise reciprocals of the ray direction
Float time; ///< Time value associated with this ray
/// Construct a new ray
inline Ray() : mint(Epsilon),
maxt(std::numeric_limits<Float>::infinity()), time(0.0f) {
}
/// Copy constructor (1)
inline Ray(const Ray &ray)
: o(ray.o), mint(ray.mint), d(ray.d), maxt(ray.maxt),
dRcp(ray.dRcp), time(ray.time) {
}
/// Copy constructor (2)
inline Ray(const Ray &ray, Float mint, Float maxt)
: o(ray.o), mint(mint), d(ray.d), maxt(maxt), dRcp(ray.dRcp), time(ray.time) {
}
/// Construct a new ray, while not specifying a direction yet
inline Ray(Point o, Float time) : o(o), mint(Epsilon), maxt(std::numeric_limits<Float>::infinity()), time(time) {
}
/// Construct a new ray
inline Ray(Point o, Vector _d, Float time)
: o(o), mint(Epsilon), d(_d), maxt(std::numeric_limits<Float>::infinity()), time(time) {
#ifdef MTS_DEBUG_FP
bool state = disableFPExceptions();
#endif
dRcp.x = (Float) 1.0f / _d.x;
dRcp.y = (Float) 1.0f / _d.y;
dRcp.z = (Float) 1.0f / _d.z;
#ifdef MTS_DEBUG_FP
restoreFPExceptions(state);
#endif
}
/// Construct a new ray
inline Ray(Point o, Vector _d, Float mint, Float maxt, Float time)
: o(o), mint(mint), d(_d), maxt(maxt), time(time) {
#ifdef MTS_DEBUG_FP
bool state = disableFPExceptions();
#endif
dRcp.x = (Float) 1.0f / _d.x;
dRcp.y = (Float) 1.0f / _d.y;
dRcp.z = (Float) 1.0f / _d.z;
#ifdef MTS_DEBUG_FP
restoreFPExceptions(state);
#endif
}
/// Set the origin
inline void setOrigin(const Point &oVal) { o = oVal; }
/// Set the origin
inline void setTime(const Float &tval) { time = tval; }
/// Set the direction and update the reciprocal
inline void setDirection(const Vector &dVal) {
d = dVal;
#ifdef MTS_DEBUG_FP
bool state = disableFPExceptions();
#endif
dRcp.x = (Float) 1.0f / dVal.x;
dRcp.y = (Float) 1.0f / dVal.y;
dRcp.z = (Float) 1.0f / dVal.z;
#ifdef MTS_DEBUG_FP
restoreFPExceptions(state);
#endif
}
/// Return 3d coordinates of a point on the ray
inline Point operator() (Float t) const { return o + t * d; }
/// Return a string representation of this ray
inline std::string toString() const {
std::ostringstream oss;
oss << "Ray[origin=" << o.toString() << ", direction="
<< d.toString() << ", mint=" << mint
<< ", maxt=" << maxt << ", time=" << time << "]";
return oss.str();
}
};
/** \brief %Ray differential -- enhances the basic ray class with
information about the rays of adjacent pixels on the view plane
\ingroup libcore
*/
struct RayDifferential : public Ray {
Point rxOrigin, ryOrigin;
Vector rxDirection, ryDirection;
bool hasDifferentials;
inline RayDifferential()
: hasDifferentials(false) {
}
inline RayDifferential(const Point &p, const Vector &d, Float time)
: Ray(p, d, time), hasDifferentials(false) {
}
inline explicit RayDifferential(const Ray &ray)
: Ray(ray), hasDifferentials(false) {
}
inline RayDifferential(const RayDifferential &ray)
: Ray(ray), rxOrigin(ray.rxOrigin), ryOrigin(ray.ryOrigin),
rxDirection(ray.rxDirection), ryDirection(ray.ryDirection),
hasDifferentials(ray.hasDifferentials) {
}
void scaleDifferential(Float amount) {
rxOrigin = o + (rxOrigin - o) * amount;
ryOrigin = o + (ryOrigin - o) * amount;
rxDirection = d + (rxDirection - d) * amount;
ryDirection = d + (ryDirection - d) * amount;
}
inline void operator=(const RayDifferential &ray) {
o = ray.o;
mint = ray.mint;
d = ray.d;
maxt = ray.maxt;
#ifdef MTS_DEBUG_FP
bool state = disableFPExceptions();
#endif
dRcp = ray.dRcp;
#ifdef MTS_DEBUG_FP
restoreFPExceptions(state);
#endif
hasDifferentials = ray.hasDifferentials;
rxOrigin = ray.rxOrigin;
ryOrigin = ray.ryOrigin;
rxDirection = ray.rxDirection;
ryDirection = ray.ryDirection;
}
inline void operator=(const Ray &ray) {
o = ray.o;
mint = ray.mint;
d = ray.d;
maxt = ray.maxt;
#ifdef MTS_DEBUG_FP
bool state = disableFPExceptions();
#endif
dRcp = ray.dRcp;
#ifdef MTS_DEBUG_FP
restoreFPExceptions(state);
#endif
hasDifferentials = false;
}
/// Return a string representation of this ray
inline std::string toString() const {
std::ostringstream oss;
oss << "RayDifferential[" << endl
<< " origin = " << o.toString() << "," << endl
<< " direction = " << d.toString() << "," << endl
<< " mint = " << mint << "," << endl
<< " maxt = " << maxt << "," << endl
<< " time = " << time << "," << endl
<< " rxOrigin = " << rxOrigin.toString() << "," << endl
<< " ryOrigin = " << ryOrigin.toString() << "," << endl
<< " rxDirection = " << rxDirection.toString() << "," << endl
<< " ryDirection = " << ryDirection.toString() << endl
<< "]" << endl;
return oss.str();
}
};
#if defined(MTS_SSE)
/** \brief SIMD quad-packed ray for coherent ray tracing */
struct RayPacket4 {
QuadVector o, d;
QuadVector dRcp;
uint8_t signs[4][4];
inline RayPacket4() {
}
inline bool load(const Ray *rays) {
for (int i=0; i<4; i++) {
for (int axis=0; axis<3; axis++) {
o[axis].f[i] = rays[i].o[axis];
d[axis].f[i] = rays[i].d[axis];
dRcp[axis].f[i] = rays[i].dRcp[axis];
signs[axis][i] = rays[i].d[axis] < 0 ? 1 : 0;
if (signs[axis][i] != signs[axis][0])
return false;
}
}
return true;
}
};
struct RayInterval4 {
SSEVector mint;
SSEVector maxt;
inline RayInterval4() {
mint = SSEConstants::eps;
maxt = SSEConstants::p_inf;
}
inline RayInterval4(const Ray *rays) {
for (int i=0; i<4; i++) {
mint.f[i] = rays[i].mint;
maxt.f[i] = rays[i].maxt;
}
}
};
struct Intersection4 {
SSEVector t;
SSEVector u;
SSEVector v;
SSEVector primIndex;
SSEVector shapeIndex;
inline Intersection4() {
t = SSEConstants::p_inf;
u = SSEConstants::zero;
v = SSEConstants::zero;
primIndex = SSEConstants::ffffffff;
shapeIndex = SSEConstants::ffffffff;
}
};
#endif
MTS_NAMESPACE_END
#endif /* __RAY_H */