Disabled external gits
This commit is contained in:
175
cs440-acg/include/nori/accel.h
Normal file
175
cs440-acg/include/nori/accel.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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(__NORI_BVH_H)
|
||||
#define __NORI_BVH_H
|
||||
|
||||
#include <nori/mesh.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Bounding Volume Hierarchy for fast ray intersection queries
|
||||
*
|
||||
* This class builds a Bounding Volume Hierarchy (BVH) using a greedy
|
||||
* divide and conquer build strategy, which locally maximizes a criterion
|
||||
* known as the Surface Area Heuristic (SAH) to obtain a tree that is
|
||||
* particularly well-suited for ray intersection queries.
|
||||
*
|
||||
* Construction of a BVH is generally slow; the implementation here runs
|
||||
* in parallel to accelerate this process much as possible. For details
|
||||
* on how this works, refer to the paper
|
||||
*
|
||||
* "Fast and Parallel Construction of SAH-based Bounding Volume Hierarchies"
|
||||
* by Ingo Wald (Proc. IEEE/EG Symposium on Interactive Ray Tracing, 2007)
|
||||
*
|
||||
* \author Wenzel Jakob
|
||||
*/
|
||||
class Accel {
|
||||
friend class BVHBuildTask;
|
||||
public:
|
||||
/// Create a new and empty BVH
|
||||
Accel() { m_meshOffset.push_back(0u); }
|
||||
|
||||
/// Release all resources
|
||||
virtual ~Accel() { clear(); };
|
||||
|
||||
/// Release all resources
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* \brief Register a triangle mesh for inclusion in the BVH.
|
||||
*
|
||||
* This function can only be used before \ref build() is called
|
||||
*/
|
||||
void addMesh(Mesh *mesh);
|
||||
|
||||
/// Build the BVH
|
||||
void build();
|
||||
|
||||
/**
|
||||
* \brief Intersect a ray against all triangle meshes registered
|
||||
* with the BVH
|
||||
*
|
||||
* Detailed information about the intersection, if any, will be
|
||||
* stored in the provided \ref Intersection data record.
|
||||
*
|
||||
* The <tt>shadowRay</tt> parameter specifies whether this detailed
|
||||
* information is really needed. When set to \c true, the
|
||||
* function just checks whether or not there is occlusion, but without
|
||||
* providing any more detail (i.e. \c its will not be filled with
|
||||
* contents). This is usually much faster.
|
||||
*
|
||||
* \return \c true If an intersection was found
|
||||
*/
|
||||
bool rayIntersect(const Ray3f &ray, Intersection &its,
|
||||
bool shadowRay = false) const;
|
||||
|
||||
/// Return the total number of meshes registered with the BVH
|
||||
uint32_t getMeshCount() const { return (uint32_t) m_meshes.size(); }
|
||||
|
||||
/// Return the total number of internally represented triangles
|
||||
uint32_t getTriangleCount() const { return m_meshOffset.back(); }
|
||||
|
||||
/// Return one of the registered meshes
|
||||
Mesh *getMesh(uint32_t idx) { return m_meshes[idx]; }
|
||||
|
||||
/// Return one of the registered meshes (const version)
|
||||
const Mesh *getMesh(uint32_t idx) const { return m_meshes[idx]; }
|
||||
|
||||
//// Return an axis-aligned bounding box containing the entire tree
|
||||
const BoundingBox3f &getBoundingBox() const {
|
||||
return m_bbox;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Compute the mesh and triangle indices corresponding to
|
||||
* a primitive index used by the underlying generic BVH implementation.
|
||||
*/
|
||||
uint32_t findMesh(uint32_t &idx) const {
|
||||
auto it = std::lower_bound(m_meshOffset.begin(), m_meshOffset.end(), idx+1) - 1;
|
||||
idx -= *it;
|
||||
return (uint32_t) (it - m_meshOffset.begin());
|
||||
}
|
||||
|
||||
//// Return an axis-aligned bounding box containing the given triangle
|
||||
BoundingBox3f getBoundingBox(uint32_t index) const {
|
||||
uint32_t meshIdx = findMesh(index);
|
||||
return m_meshes[meshIdx]->getBoundingBox(index);
|
||||
}
|
||||
|
||||
//// Return the centroid of the given triangle
|
||||
Point3f getCentroid(uint32_t index) const {
|
||||
uint32_t meshIdx = findMesh(index);
|
||||
return m_meshes[meshIdx]->getCentroid(index);
|
||||
}
|
||||
|
||||
/// Compute internal tree statistics
|
||||
std::pair<float, uint32_t> statistics(uint32_t index = 0) const;
|
||||
|
||||
/* BVH node in 32 bytes */
|
||||
struct BVHNode {
|
||||
union {
|
||||
struct {
|
||||
unsigned flag : 1;
|
||||
uint32_t size : 31;
|
||||
uint32_t start;
|
||||
} leaf;
|
||||
|
||||
struct {
|
||||
unsigned flag : 1;
|
||||
uint32_t axis : 31;
|
||||
uint32_t rightChild;
|
||||
} inner;
|
||||
|
||||
uint64_t data;
|
||||
};
|
||||
BoundingBox3f bbox;
|
||||
|
||||
bool isLeaf() const {
|
||||
return leaf.flag == 1;
|
||||
}
|
||||
|
||||
bool isInner() const {
|
||||
return leaf.flag == 0;
|
||||
}
|
||||
|
||||
bool isUnused() const {
|
||||
return data == 0;
|
||||
}
|
||||
|
||||
uint32_t start() const {
|
||||
return leaf.start;
|
||||
}
|
||||
|
||||
uint32_t end() const {
|
||||
return leaf.start + leaf.size;
|
||||
}
|
||||
};
|
||||
private:
|
||||
std::vector<Mesh *> m_meshes; ///< List of meshes registered with the BVH
|
||||
std::vector<uint32_t> m_meshOffset; ///< Index of the first triangle for each shape
|
||||
std::vector<BVHNode> m_nodes; ///< BVH nodes
|
||||
std::vector<uint32_t> m_indices; ///< Index references by BVH nodes
|
||||
BoundingBox3f m_bbox; ///< Bounding box of the entire BVH
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
||||
|
||||
#endif /* __NORI_BVH_H */
|
399
cs440-acg/include/nori/bbox.h
Normal file
399
cs440-acg/include/nori/bbox.h
Normal file
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/ray.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Generic n-dimensional bounding box data structure
|
||||
*
|
||||
* Maintains a minimum and maximum position along each dimension and provides
|
||||
* various convenience functions for querying and modifying them.
|
||||
*
|
||||
* This class is parameterized by the underlying point data structure,
|
||||
* which permits the use of different scalar types and dimensionalities, e.g.
|
||||
* \code
|
||||
* TBoundingBox<Vector3i> integerBBox(Point3i(0, 1, 3), Point3i(4, 5, 6));
|
||||
* TBoundingBox<Vector2d> doubleBBox(Point2d(0.0, 1.0), Point2d(4.0, 5.0));
|
||||
* \endcode
|
||||
*
|
||||
* \tparam T The underlying point data type (e.g. \c Point2d)
|
||||
* \ingroup libcore
|
||||
*/
|
||||
template <typename _PointType> struct TBoundingBox {
|
||||
enum {
|
||||
Dimension = _PointType::Dimension
|
||||
};
|
||||
|
||||
typedef _PointType PointType;
|
||||
typedef typename PointType::Scalar Scalar;
|
||||
typedef typename PointType::VectorType VectorType;
|
||||
|
||||
/**
|
||||
* \brief Create a new invalid bounding box
|
||||
*
|
||||
* Initializes the components of the minimum
|
||||
* and maximum position to \f$\infty\f$ and \f$-\infty\f$,
|
||||
* respectively.
|
||||
*/
|
||||
TBoundingBox() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/// Create a collapsed bounding box from a single point
|
||||
TBoundingBox(const PointType &p)
|
||||
: min(p), max(p) { }
|
||||
|
||||
/// Create a bounding box from two positions
|
||||
TBoundingBox(const PointType &min, const PointType &max)
|
||||
: min(min), max(max) {
|
||||
}
|
||||
|
||||
/// Test for equality against another bounding box
|
||||
bool operator==(const TBoundingBox &bbox) const {
|
||||
return min == bbox.min && max == bbox.max;
|
||||
}
|
||||
|
||||
/// Test for inequality against another bounding box
|
||||
bool operator!=(const TBoundingBox &bbox) const {
|
||||
return min != bbox.min || max != bbox.max;
|
||||
}
|
||||
|
||||
/// Calculate the n-dimensional volume of the bounding box
|
||||
Scalar getVolume() const {
|
||||
return (max - min).prod();
|
||||
}
|
||||
|
||||
/// Calculate the n-1 dimensional volume of the boundary
|
||||
float getSurfaceArea() const {
|
||||
VectorType d = max - min;
|
||||
float result = 0.0f;
|
||||
for (int i=0; i<Dimension; ++i) {
|
||||
float term = 1.0f;
|
||||
for (int j=0; j<Dimension; ++j) {
|
||||
if (i == j)
|
||||
continue;
|
||||
term *= d[j];
|
||||
}
|
||||
result += term;
|
||||
}
|
||||
return 2.0f * result;
|
||||
}
|
||||
|
||||
/// Return the center point
|
||||
PointType getCenter() const {
|
||||
return (max + min) * (Scalar) 0.5f;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check whether a point lies \a on or \a inside the bounding box
|
||||
*
|
||||
* \param p The point to be tested
|
||||
*
|
||||
* \param strict Set this parameter to \c true if the bounding
|
||||
* box boundary should be excluded in the test
|
||||
*/
|
||||
bool contains(const PointType &p, bool strict = false) const {
|
||||
if (strict) {
|
||||
return (p.array() > min.array()).all()
|
||||
&& (p.array() < max.array()).all();
|
||||
} else {
|
||||
return (p.array() >= min.array()).all()
|
||||
&& (p.array() <= max.array()).all();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check whether a specified bounding box lies \a on or \a within
|
||||
* the current bounding box
|
||||
*
|
||||
* Note that by definition, an 'invalid' bounding box (where min=\f$\infty\f$
|
||||
* and max=\f$-\infty\f$) does not cover any space. Hence, this method will always
|
||||
* return \a true when given such an argument.
|
||||
*
|
||||
* \param strict Set this parameter to \c true if the bounding
|
||||
* box boundary should be excluded in the test
|
||||
*/
|
||||
bool contains(const TBoundingBox &bbox, bool strict = false) const {
|
||||
if (strict) {
|
||||
return (bbox.min.array() > min.array()).all()
|
||||
&& (bbox.max.array() < max.array()).all();
|
||||
} else {
|
||||
return (bbox.min.array() >= min.array()).all()
|
||||
&& (bbox.max.array() <= max.array()).all();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check two axis-aligned bounding boxes for possible overlap.
|
||||
*
|
||||
* \param strict Set this parameter to \c true if the bounding
|
||||
* box boundary should be excluded in the test
|
||||
*
|
||||
* \return \c true If overlap was detected.
|
||||
*/
|
||||
bool overlaps(const TBoundingBox &bbox, bool strict = false) const {
|
||||
if (strict) {
|
||||
return (bbox.min.array() < max.array()).all()
|
||||
&& (bbox.max.array() > min.array()).all();
|
||||
} else {
|
||||
return (bbox.min.array() <= max.array()).all()
|
||||
&& (bbox.max.array() >= min.array()).all();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate the smallest squared distance between
|
||||
* the axis-aligned bounding box and the point \c p.
|
||||
*/
|
||||
Scalar squaredDistanceTo(const PointType &p) const {
|
||||
Scalar result = 0;
|
||||
|
||||
for (int i=0; i<Dimension; ++i) {
|
||||
Scalar value = 0;
|
||||
if (p[i] < min[i])
|
||||
value = min[i] - p[i];
|
||||
else if (p[i] > max[i])
|
||||
value = p[i] - max[i];
|
||||
result += value*value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate the smallest distance between
|
||||
* the axis-aligned bounding box and the point \c p.
|
||||
*/
|
||||
Scalar distanceTo(const PointType &p) const {
|
||||
return std::sqrt(squaredDistanceTo(p));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate the smallest square distance between
|
||||
* the axis-aligned bounding box and \c bbox.
|
||||
*/
|
||||
Scalar squaredDistanceTo(const TBoundingBox &bbox) const {
|
||||
Scalar result = 0;
|
||||
|
||||
for (int i=0; i<Dimension; ++i) {
|
||||
Scalar value = 0;
|
||||
if (bbox.max[i] < min[i])
|
||||
value = min[i] - bbox.max[i];
|
||||
else if (bbox.min[i] > max[i])
|
||||
value = bbox.min[i] - max[i];
|
||||
result += value*value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate the smallest distance between
|
||||
* the axis-aligned bounding box and \c bbox.
|
||||
*/
|
||||
Scalar distanceTo(const TBoundingBox &bbox) const {
|
||||
return std::sqrt(squaredDistanceTo(bbox));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check whether this is a valid bounding box
|
||||
*
|
||||
* A bounding box \c bbox is valid when
|
||||
* \code
|
||||
* bbox.min[dim] <= bbox.max[dim]
|
||||
* \endcode
|
||||
* holds along each dimension \c dim.
|
||||
*/
|
||||
bool isValid() const {
|
||||
return (max.array() >= min.array()).all();
|
||||
}
|
||||
|
||||
/// Check whether this bounding box has collapsed to a single point
|
||||
bool isPoint() const {
|
||||
return (max.array() == min.array()).all();
|
||||
}
|
||||
|
||||
/// Check whether this bounding box has any associated volume
|
||||
bool hasVolume() const {
|
||||
return (max.array() > min.array()).all();
|
||||
}
|
||||
|
||||
/// Return the dimension index with the largest associated side length
|
||||
int getMajorAxis() const {
|
||||
VectorType d = max - min;
|
||||
int largest = 0;
|
||||
for (int i=1; i<Dimension; ++i)
|
||||
if (d[i] > d[largest])
|
||||
largest = i;
|
||||
return largest;
|
||||
}
|
||||
|
||||
/// Return the dimension index with the shortest associated side length
|
||||
int getMinorAxis() const {
|
||||
VectorType d = max - min;
|
||||
int shortest = 0;
|
||||
for (int i=1; i<Dimension; ++i)
|
||||
if (d[i] < d[shortest])
|
||||
shortest = i;
|
||||
return shortest;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Calculate the bounding box extents
|
||||
* \return max-min
|
||||
*/
|
||||
VectorType getExtents() const {
|
||||
return max - min;
|
||||
}
|
||||
|
||||
/// Clip to another bounding box
|
||||
void clip(const TBoundingBox &bbox) {
|
||||
min = min.cwiseMax(bbox.min);
|
||||
max = max.cwiseMin(bbox.max);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark the bounding box as invalid.
|
||||
*
|
||||
* This operation sets the components of the minimum
|
||||
* and maximum position to \f$\infty\f$ and \f$-\infty\f$,
|
||||
* respectively.
|
||||
*/
|
||||
void reset() {
|
||||
min.setConstant( std::numeric_limits<Scalar>::infinity());
|
||||
max.setConstant(-std::numeric_limits<Scalar>::infinity());
|
||||
}
|
||||
|
||||
/// Expand the bounding box to contain another point
|
||||
void expandBy(const PointType &p) {
|
||||
min = min.cwiseMin(p);
|
||||
max = max.cwiseMax(p);
|
||||
}
|
||||
|
||||
/// Expand the bounding box to contain another bounding box
|
||||
void expandBy(const TBoundingBox &bbox) {
|
||||
min = min.cwiseMin(bbox.min);
|
||||
max = max.cwiseMax(bbox.max);
|
||||
}
|
||||
|
||||
/// Merge two bounding boxes
|
||||
static TBoundingBox merge(const TBoundingBox &bbox1, const TBoundingBox &bbox2) {
|
||||
return TBoundingBox(
|
||||
bbox1.min.cwiseMin(bbox2.min),
|
||||
bbox1.max.cwiseMax(bbox2.max)
|
||||
);
|
||||
}
|
||||
|
||||
/// Return the index of the largest axis
|
||||
int getLargestAxis() const {
|
||||
VectorType extents = max-min;
|
||||
|
||||
if (extents[0] >= extents[1] && extents[0] >= extents[2])
|
||||
return 0;
|
||||
else if (extents[1] >= extents[0] && extents[1] >= extents[2])
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
/// Return the position of a bounding box corner
|
||||
PointType getCorner(int index) const {
|
||||
PointType result;
|
||||
for (int i=0; i<Dimension; ++i)
|
||||
result[i] = (index & (1 << i)) ? max[i] : min[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Return a string representation of the bounding box
|
||||
std::string toString() const {
|
||||
if (!isValid())
|
||||
return "BoundingBox[invalid]";
|
||||
else
|
||||
return tfm::format("BoundingBox[min=%s, max=%s]", min.toString(), max.toString());
|
||||
}
|
||||
|
||||
/// Check if a ray intersects a bounding box
|
||||
bool rayIntersect(const Ray3f &ray) const {
|
||||
float nearT = -std::numeric_limits<float>::infinity();
|
||||
float farT = std::numeric_limits<float>::infinity();
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
float origin = ray.o[i];
|
||||
float minVal = min[i], maxVal = max[i];
|
||||
|
||||
if (ray.d[i] == 0) {
|
||||
if (origin < minVal || origin > maxVal)
|
||||
return false;
|
||||
} else {
|
||||
float t1 = (minVal - origin) * ray.dRcp[i];
|
||||
float t2 = (maxVal - origin) * ray.dRcp[i];
|
||||
|
||||
if (t1 > t2)
|
||||
std::swap(t1, t2);
|
||||
|
||||
nearT = std::max(t1, nearT);
|
||||
farT = std::min(t2, farT);
|
||||
|
||||
if (!(nearT <= farT))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return ray.mint <= farT && nearT <= ray.maxt;
|
||||
}
|
||||
|
||||
/// Return the overlapping region of the bounding box and an unbounded ray
|
||||
bool rayIntersect(const Ray3f &ray, float &nearT, float &farT) const {
|
||||
nearT = -std::numeric_limits<float>::infinity();
|
||||
farT = std::numeric_limits<float>::infinity();
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
float origin = ray.o[i];
|
||||
float minVal = min[i], maxVal = max[i];
|
||||
|
||||
if (ray.d[i] == 0) {
|
||||
if (origin < minVal || origin > maxVal)
|
||||
return false;
|
||||
} else {
|
||||
float t1 = (minVal - origin) * ray.dRcp[i];
|
||||
float t2 = (maxVal - origin) * ray.dRcp[i];
|
||||
|
||||
if (t1 > t2)
|
||||
std::swap(t1, t2);
|
||||
|
||||
nearT = std::max(t1, nearT);
|
||||
farT = std::min(t2, farT);
|
||||
|
||||
if (!(nearT <= farT))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PointType min; ///< Component-wise minimum
|
||||
PointType max; ///< Component-wise maximum
|
||||
};
|
||||
|
||||
|
||||
NORI_NAMESPACE_END
|
54
cs440-acg/include/nori/bitmap.h
Normal file
54
cs440-acg/include/nori/bitmap.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/color.h>
|
||||
#include <nori/vector.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Stores a RGB high dynamic-range bitmap
|
||||
*
|
||||
* The bitmap class provides I/O support using the OpenEXR file format
|
||||
*/
|
||||
class Bitmap : public Eigen::Array<Color3f, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> {
|
||||
public:
|
||||
typedef Eigen::Array<Color3f, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> Base;
|
||||
|
||||
/**
|
||||
* \brief Allocate a new bitmap of the specified size
|
||||
*
|
||||
* The contents will initially be undefined, so make sure
|
||||
* to call \ref clear() if necessary
|
||||
*/
|
||||
Bitmap(const Vector2i &size = Vector2i(0, 0))
|
||||
: Base(size.y(), size.x()) { }
|
||||
|
||||
/// Load an OpenEXR file with the specified filename
|
||||
Bitmap(const std::string &filename);
|
||||
|
||||
/// Save the bitmap as an EXR file with the specified filename
|
||||
void saveEXR(const std::string &filename);
|
||||
|
||||
/// Save the bitmap as a PNG file (with sRGB tonemapping) with the specified filename
|
||||
void savePNG(const std::string &filename);
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
166
cs440-acg/include/nori/block.h
Normal file
166
cs440-acg/include/nori/block.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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/>.
|
||||
*/
|
||||
|
||||
/* =======================================================================
|
||||
This file contains classes for parallel rendering of "image blocks".
|
||||
* ======================================================================= */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nori/color.h>
|
||||
#include <nori/vector.h>
|
||||
#include <tbb/mutex.h>
|
||||
|
||||
#define NORI_BLOCK_SIZE 32 /* Block size used for parallelization */
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Weighted pixel storage for a rectangular subregion of an image
|
||||
*
|
||||
* This class implements storage for a rectangular subregion of a
|
||||
* larger image that is being rendered. For each pixel, it records color
|
||||
* values along with a weight that specifies the accumulated influence of
|
||||
* nearby samples on the pixel (according to the used reconstruction filter).
|
||||
*
|
||||
* When rendering with filters, the samples in a rectangular
|
||||
* region will generally also contribute to pixels just outside of
|
||||
* this region. For that reason, this class also stores information about
|
||||
* a small border region around the rectangle, whose size depends on the
|
||||
* properties of the reconstruction filter.
|
||||
*/
|
||||
class ImageBlock : public Eigen::Array<Color4f, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> {
|
||||
public:
|
||||
/**
|
||||
* Create a new image block of the specified maximum size
|
||||
* \param size
|
||||
* Desired maximum size of the block
|
||||
* \param filter
|
||||
* Samples will be convolved with the image reconstruction
|
||||
* filter provided here.
|
||||
*/
|
||||
ImageBlock(const Vector2i &size, const ReconstructionFilter *filter);
|
||||
|
||||
/// Release all memory
|
||||
~ImageBlock();
|
||||
|
||||
/// Configure the offset of the block within the main image
|
||||
void setOffset(const Point2i &offset) { m_offset = offset; }
|
||||
|
||||
/// Return the offset of the block within the main image
|
||||
inline const Point2i &getOffset() const { return m_offset; }
|
||||
|
||||
/// Configure the size of the block within the main image
|
||||
void setSize(const Point2i &size) { m_size = size; }
|
||||
|
||||
/// Return the size of the block within the main image
|
||||
inline const Vector2i &getSize() const { return m_size; }
|
||||
|
||||
/// Return the border size in pixels
|
||||
inline int getBorderSize() const { return m_borderSize; }
|
||||
|
||||
/**
|
||||
* \brief Turn the block into a proper bitmap
|
||||
*
|
||||
* This entails normalizing all pixels and discarding
|
||||
* the border region.
|
||||
*/
|
||||
Bitmap *toBitmap() const;
|
||||
|
||||
/// Convert a bitmap into an image block
|
||||
void fromBitmap(const Bitmap &bitmap);
|
||||
|
||||
/// Clear all contents
|
||||
void clear() { setConstant(Color4f()); }
|
||||
|
||||
/// Record a sample with the given position and radiance value
|
||||
void put(const Point2f &pos, const Color3f &value);
|
||||
|
||||
/**
|
||||
* \brief Merge another image block into this one
|
||||
*
|
||||
* During the merge operation, this function locks
|
||||
* the destination block using a mutex.
|
||||
*/
|
||||
void put(ImageBlock &b);
|
||||
|
||||
/// Lock the image block (using an internal mutex)
|
||||
inline void lock() const { m_mutex.lock(); }
|
||||
|
||||
/// Unlock the image block
|
||||
inline void unlock() const { m_mutex.unlock(); }
|
||||
|
||||
/// Return a human-readable string summary
|
||||
std::string toString() const;
|
||||
protected:
|
||||
Point2i m_offset;
|
||||
Vector2i m_size;
|
||||
int m_borderSize = 0;
|
||||
float *m_filter = nullptr;
|
||||
float m_filterRadius = 0;
|
||||
float *m_weightsX = nullptr;
|
||||
float *m_weightsY = nullptr;
|
||||
float m_lookupFactor = 0;
|
||||
mutable tbb::mutex m_mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Spiraling block generator
|
||||
*
|
||||
* This class can be used to chop up an image into many small
|
||||
* rectangular blocks suitable for parallel rendering. The blocks
|
||||
* are ordered in spiraling pattern so that the center is
|
||||
* rendered first.
|
||||
*/
|
||||
class BlockGenerator {
|
||||
public:
|
||||
/**
|
||||
* \brief Create a block generator with
|
||||
* \param size
|
||||
* Size of the image that should be split into blocks
|
||||
* \param blockSize
|
||||
* Maximum size of the individual blocks
|
||||
*/
|
||||
BlockGenerator(const Vector2i &size, int blockSize);
|
||||
|
||||
/**
|
||||
* \brief Return the next block to be rendered
|
||||
*
|
||||
* This function is thread-safe
|
||||
*
|
||||
* \return \c false if there were no more blocks
|
||||
*/
|
||||
bool next(ImageBlock &block);
|
||||
|
||||
/// Return the total number of blocks
|
||||
int getBlockCount() const { return m_blocksLeft; }
|
||||
protected:
|
||||
enum EDirection { ERight = 0, EDown, ELeft, EUp };
|
||||
|
||||
Point2i m_block;
|
||||
Vector2i m_numBlocks;
|
||||
Vector2i m_size;
|
||||
int m_blockSize;
|
||||
int m_numSteps;
|
||||
int m_blocksLeft;
|
||||
int m_stepsLeft;
|
||||
int m_direction;
|
||||
tbb::mutex m_mutex;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
117
cs440-acg/include/nori/bsdf.h
Normal file
117
cs440-acg/include/nori/bsdf.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/object.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Convenience data structure used to pass multiple
|
||||
* parameters to the evaluation and sampling routines in \ref BSDF
|
||||
*/
|
||||
struct BSDFQueryRecord {
|
||||
/// Incident direction (in the local frame)
|
||||
Vector3f wi;
|
||||
|
||||
/// Outgoing direction (in the local frame)
|
||||
Vector3f wo;
|
||||
|
||||
/// Relative refractive index in the sampled direction
|
||||
float eta;
|
||||
|
||||
Point2f uv;
|
||||
|
||||
/// Measure associated with the sample
|
||||
EMeasure measure;
|
||||
|
||||
/// Create a new record for sampling the BSDF
|
||||
BSDFQueryRecord(const Vector3f &wi)
|
||||
: wi(wi), eta(1.f), measure(EUnknownMeasure) { }
|
||||
|
||||
/// Create a new record for querying the BSDF
|
||||
BSDFQueryRecord(const Vector3f &wi,
|
||||
const Vector3f &wo, EMeasure measure)
|
||||
: wi(wi), wo(wo), eta(1.f), measure(measure) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Superclass of all bidirectional scattering distribution functions
|
||||
*/
|
||||
class BSDF : public NoriObject {
|
||||
public:
|
||||
/**
|
||||
* \brief Sample the BSDF and return the importance weight (i.e. the
|
||||
* value of the BSDF * cos(theta_o) divided by the probability density
|
||||
* of the sample with respect to solid angles).
|
||||
*
|
||||
* \param bRec A BSDF query record
|
||||
* \param sample A uniformly distributed sample on \f$[0,1]^2\f$
|
||||
*
|
||||
* \return The BSDF value divided by the probability density of the sample
|
||||
* sample. The returned value also includes the cosine
|
||||
* foreshortening factor associated with the outgoing direction,
|
||||
* when this is appropriate. A zero value means that sampling
|
||||
* failed.
|
||||
*/
|
||||
virtual Color3f sample(BSDFQueryRecord &bRec, const Point2f &sample) const = 0;
|
||||
|
||||
/**
|
||||
* \brief Evaluate the BSDF for a pair of directions and measure
|
||||
* specified in \code bRec
|
||||
*
|
||||
* \param bRec
|
||||
* A record with detailed information on the BSDF query
|
||||
* \return
|
||||
* The BSDF value, evaluated for each color channel
|
||||
*/
|
||||
virtual Color3f eval(const BSDFQueryRecord &bRec) const = 0;
|
||||
|
||||
/**
|
||||
* \brief Compute the probability of sampling \c bRec.wo
|
||||
* (conditioned on \c bRec.wi).
|
||||
*
|
||||
* This method provides access to the probability density that
|
||||
* is realized by the \ref sample() method.
|
||||
*
|
||||
* \param bRec
|
||||
* A record with detailed information on the BSDF query
|
||||
*
|
||||
* \return
|
||||
* A probability/density value expressed with respect
|
||||
* to the specified measure
|
||||
*/
|
||||
|
||||
virtual float pdf(const BSDFQueryRecord &bRec) const = 0;
|
||||
|
||||
/**
|
||||
* \brief Return the type of object (i.e. Mesh/BSDF/etc.)
|
||||
* provided by this instance
|
||||
* */
|
||||
EClassType getClassType() const { return EBSDF; }
|
||||
|
||||
/**
|
||||
* \brief Return whether or not this BRDF is diffuse. This
|
||||
* is primarily used by photon mapping to decide whether
|
||||
* or not to store photons on a surface
|
||||
*/
|
||||
virtual bool isDiffuse() const { return false; }
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
76
cs440-acg/include/nori/camera.h
Normal file
76
cs440-acg/include/nori/camera.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/object.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Generic camera interface
|
||||
*
|
||||
* This class provides an abstract interface to cameras in Nori and
|
||||
* exposes the ability to sample their response function. By default, only
|
||||
* a perspective camera implementation exists, but you may choose to
|
||||
* implement other types (e.g. an environment camera, or a physically-based
|
||||
* camera model that simulates the behavior actual lenses)
|
||||
*/
|
||||
class Camera : public NoriObject {
|
||||
public:
|
||||
/**
|
||||
* \brief Importance sample a ray according to the camera's response function
|
||||
*
|
||||
* \param ray
|
||||
* A ray data structure to be filled with a position
|
||||
* and direction value
|
||||
*
|
||||
* \param samplePosition
|
||||
* Denotes the desired sample position on the film
|
||||
* expressed in fractional pixel coordinates
|
||||
*
|
||||
* \param apertureSample
|
||||
* A uniformly distributed 2D vector that is used to sample
|
||||
* a position on the aperture of the sensor if necessary.
|
||||
*
|
||||
* \return
|
||||
* An importance weight associated with the sampled ray.
|
||||
* This accounts for the difference in the camera response
|
||||
* function and the sampling density.
|
||||
*/
|
||||
virtual Color3f sampleRay(Ray3f &ray,
|
||||
const Point2f &samplePosition,
|
||||
const Point2f &apertureSample) const = 0;
|
||||
|
||||
/// Return the size of the output image in pixels
|
||||
const Vector2i &getOutputSize() const { return m_outputSize; }
|
||||
|
||||
/// Return the camera's reconstruction filter in image space
|
||||
const ReconstructionFilter *getReconstructionFilter() const { return m_rfilter; }
|
||||
|
||||
/**
|
||||
* \brief Return the type of object (i.e. Mesh/Camera/etc.)
|
||||
* provided by this instance
|
||||
* */
|
||||
EClassType getClassType() const { return ECamera; }
|
||||
protected:
|
||||
Vector2i m_outputSize;
|
||||
ReconstructionFilter *m_rfilter;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
138
cs440-acg/include/nori/color.h
Normal file
138
cs440-acg/include/nori/color.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/common.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Represents a linear RGB color value
|
||||
*/
|
||||
struct Color3f : public Eigen::Array3f {
|
||||
public:
|
||||
typedef Eigen::Array3f Base;
|
||||
|
||||
/// Initialize the color vector with a uniform value
|
||||
Color3f(float value = 0.f) : Base(value, value, value) { }
|
||||
|
||||
/// Initialize the color vector with specific per-channel values
|
||||
Color3f(float r, float g, float b) : Base(r, g, b) { }
|
||||
|
||||
/// Construct a color vector from ArrayBase (needed to play nice with Eigen)
|
||||
template <typename Derived> Color3f(const Eigen::ArrayBase<Derived>& p)
|
||||
: Base(p) { }
|
||||
|
||||
/// Assign a color vector from ArrayBase (needed to play nice with Eigen)
|
||||
template <typename Derived> Color3f &operator=(const Eigen::ArrayBase<Derived>& p) {
|
||||
this->Base::operator=(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Return a reference to the red channel
|
||||
float &r() { return x(); }
|
||||
/// Return a reference to the red channel (const version)
|
||||
const float &r() const { return x(); }
|
||||
/// Return a reference to the green channel
|
||||
float &g() { return y(); }
|
||||
/// Return a reference to the green channel (const version)
|
||||
const float &g() const { return y(); }
|
||||
/// Return a reference to the blue channel
|
||||
float &b() { return z(); }
|
||||
/// Return a reference to the blue channel (const version)
|
||||
const float &b() const { return z(); }
|
||||
|
||||
/// Clamp to the positive range
|
||||
Color3f clamp() const { return Color3f(std::max(r(), 0.0f),
|
||||
std::max(g(), 0.0f), std::max(b(), 0.0f)); }
|
||||
|
||||
/// Check if the color vector contains a NaN/Inf/negative value
|
||||
bool isValid() const;
|
||||
|
||||
/// Convert from sRGB to linear RGB
|
||||
Color3f toLinearRGB() const;
|
||||
|
||||
/// Convert from linear RGB to sRGB
|
||||
Color3f toSRGB() const;
|
||||
|
||||
/// Return the associated luminance
|
||||
float getLuminance() const;
|
||||
|
||||
/// Return a human-readable string summary
|
||||
std::string toString() const {
|
||||
return tfm::format("[%f, %f, %f]", coeff(0), coeff(1), coeff(2));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline Color3f lerp(float v, const Color3f& a, const Color3f& b){
|
||||
return (1.0-v)*a + v * b;
|
||||
}
|
||||
|
||||
inline Color3f bilerp(float x, float y, const Color3f& a, const Color3f& b, const Color3f& c, const Color3f& d){
|
||||
return a*(1.0-x)*(1.0-y)+
|
||||
b*(x)*(1.0-y)+
|
||||
c*(1.0-x)*(y)+
|
||||
d*(x)*(y);;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Represents a linear RGB color and a weight
|
||||
*
|
||||
* This is used by Nori's image reconstruction filter code
|
||||
*/
|
||||
struct Color4f : public Eigen::Array4f {
|
||||
public:
|
||||
typedef Eigen::Array4f Base;
|
||||
|
||||
/// Create an zero value
|
||||
Color4f() : Base(0.0f, 0.0f, 0.0f, 0.0f) { }
|
||||
|
||||
/// Create from a 3-channel color
|
||||
Color4f(const Color3f &c) : Base(c.r(), c.g(), c.b(), 1.0f) { }
|
||||
|
||||
/// Initialize the color vector with specific per-channel values
|
||||
Color4f(float r, float g, float b, float w) : Base(r, g, b, w) { }
|
||||
|
||||
/// Construct a color vector from ArrayBase (needed to play nice with Eigen)
|
||||
template <typename Derived> Color4f(const Eigen::ArrayBase<Derived>& p)
|
||||
: Base(p) { }
|
||||
|
||||
/// Assign a color vector from ArrayBase (needed to play nice with Eigen)
|
||||
template <typename Derived> Color4f &operator=(const Eigen::ArrayBase<Derived>& p) {
|
||||
this->Base::operator=(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Divide by the filter weight and convert into a \ref Color3f value
|
||||
Color3f divideByFilterWeight() const {
|
||||
if (w() != 0)
|
||||
return head<3>() / w();
|
||||
else
|
||||
return Color3f(0.0f);
|
||||
}
|
||||
|
||||
/// Return a human-readable string summary
|
||||
std::string toString() const {
|
||||
return tfm::format("[%f, %f, %f, %f]", coeff(0), coeff(1), coeff(2), coeff(3));
|
||||
}
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
275
cs440-acg/include/nori/common.h
Normal file
275
cs440-acg/include/nori/common.h
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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(_MSC_VER)
|
||||
/* Disable some warnings on MSVC++ */
|
||||
#pragma warning(disable : 4127 4702 4100 4515 4800 4146 4512)
|
||||
#define WIN32_LEAN_AND_MEAN /* Don't ever include MFC on Windows */
|
||||
#define NOMINMAX /* Don't override min/max */
|
||||
#endif
|
||||
|
||||
/* Include the basics needed by any Nori file */
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <Eigen/Core>
|
||||
#include <stdint.h>
|
||||
#include <ImathPlatform.h>
|
||||
#include <tinyformat.h>
|
||||
|
||||
/* Convenience definitions */
|
||||
#define NORI_NAMESPACE_BEGIN namespace nori {
|
||||
#define NORI_NAMESPACE_END }
|
||||
|
||||
#if defined(__NORI_APPLE__NORI_)
|
||||
#define PLATFORM_MACOS
|
||||
#elif defined(__NORI_linux__NORI_)
|
||||
#define PLATFORM_LINUX
|
||||
#elif defined(WIN32)
|
||||
#define PLATFORM_WINDOWS
|
||||
#endif
|
||||
|
||||
/* "Ray epsilon": relative error threshold for ray intersection computations */
|
||||
#define Epsilon 1e-4f
|
||||
|
||||
/* A few useful constants */
|
||||
#undef M_PI
|
||||
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#define INV_PI 0.31830988618379067154f
|
||||
#define INV_TWOPI 0.15915494309189533577f
|
||||
#define INV_FOURPI 0.07957747154594766788f
|
||||
#define SQRT_TWO 1.41421356237309504880f
|
||||
#define INV_SQRT_TWO 0.70710678118654752440f
|
||||
|
||||
/* Forward declarations */
|
||||
namespace filesystem {
|
||||
class path;
|
||||
class resolver;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/* Forward declarations */
|
||||
template <typename Scalar, int Dimension> struct TVector;
|
||||
template <typename Scalar, int Dimension> struct TPoint;
|
||||
template <typename Point, typename Vector> struct TRay;
|
||||
template <typename Point> struct TBoundingBox;
|
||||
|
||||
/* Basic Nori data structures (vectors, points, rays, bounding boxes,
|
||||
kd-trees) are oblivious to the underlying data type and dimension.
|
||||
The following list of typedefs establishes some convenient aliases
|
||||
for specific types. */
|
||||
typedef TVector<float, 1> Vector1f;
|
||||
typedef TVector<float, 2> Vector2f;
|
||||
typedef TVector<float, 3> Vector3f;
|
||||
typedef TVector<float, 4> Vector4f;
|
||||
typedef TVector<double, 1> Vector1d;
|
||||
typedef TVector<double, 2> Vector2d;
|
||||
typedef TVector<double, 3> Vector3d;
|
||||
typedef TVector<double, 4> Vector4d;
|
||||
typedef TVector<int, 1> Vector1i;
|
||||
typedef TVector<int, 2> Vector2i;
|
||||
typedef TVector<int, 3> Vector3i;
|
||||
typedef TVector<int, 4> Vector4i;
|
||||
typedef TPoint<float, 1> Point1f;
|
||||
typedef TPoint<float, 2> Point2f;
|
||||
typedef TPoint<float, 3> Point3f;
|
||||
typedef TPoint<float, 4> Point4f;
|
||||
typedef TPoint<double, 1> Point1d;
|
||||
typedef TPoint<double, 2> Point2d;
|
||||
typedef TPoint<double, 3> Point3d;
|
||||
typedef TPoint<double, 4> Point4d;
|
||||
typedef TPoint<int, 1> Point1i;
|
||||
typedef TPoint<int, 2> Point2i;
|
||||
typedef TPoint<int, 3> Point3i;
|
||||
typedef TPoint<int, 4> Point4i;
|
||||
typedef TBoundingBox<Point1f> BoundingBox1f;
|
||||
typedef TBoundingBox<Point2f> BoundingBox2f;
|
||||
typedef TBoundingBox<Point3f> BoundingBox3f;
|
||||
typedef TBoundingBox<Point4f> BoundingBox4f;
|
||||
typedef TBoundingBox<Point1d> BoundingBox1d;
|
||||
typedef TBoundingBox<Point2d> BoundingBox2d;
|
||||
typedef TBoundingBox<Point3d> BoundingBox3d;
|
||||
typedef TBoundingBox<Point4d> BoundingBox4d;
|
||||
typedef TBoundingBox<Point1i> BoundingBox1i;
|
||||
typedef TBoundingBox<Point2i> BoundingBox2i;
|
||||
typedef TBoundingBox<Point3i> BoundingBox3i;
|
||||
typedef TBoundingBox<Point4i> BoundingBox4i;
|
||||
typedef TRay<Point2f, Vector2f> Ray2f;
|
||||
typedef TRay<Point3f, Vector3f> Ray3f;
|
||||
|
||||
/// Some more forward declarations
|
||||
class BSDF;
|
||||
class Bitmap;
|
||||
class BlockGenerator;
|
||||
class Camera;
|
||||
class ImageBlock;
|
||||
class Integrator;
|
||||
class KDTree;
|
||||
class Emitter;
|
||||
struct EmitterQueryRecord;
|
||||
class Mesh;
|
||||
class NoriObject;
|
||||
class NoriObjectFactory;
|
||||
class NoriScreen;
|
||||
class PhaseFunction;
|
||||
class ReconstructionFilter;
|
||||
class Sampler;
|
||||
class Scene;
|
||||
|
||||
/// Import cout, cerr, endl for debugging purposes
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> MatrixXf;
|
||||
typedef Eigen::Matrix<uint32_t, Eigen::Dynamic, Eigen::Dynamic> MatrixXu;
|
||||
|
||||
/// Simple exception class, which stores a human-readable error description
|
||||
class NoriException : public std::runtime_error {
|
||||
public:
|
||||
/// Variadic template constructor to support printf-style arguments
|
||||
template <typename... Args> NoriException(const char *fmt, const Args &... args)
|
||||
: std::runtime_error(tfm::format(fmt, args...)) { }
|
||||
};
|
||||
|
||||
/// Return the number of cores (real and virtual)
|
||||
extern int getCoreCount();
|
||||
|
||||
/// Indent a string by the specified number of spaces
|
||||
extern std::string indent(const std::string &string, int amount = 2);
|
||||
|
||||
/// Convert a string to lower case
|
||||
extern std::string toLower(const std::string &value);
|
||||
|
||||
/// Convert a string into an boolean value
|
||||
extern bool toBool(const std::string &str);
|
||||
|
||||
/// Convert a string into a signed integer value
|
||||
extern int toInt(const std::string &str);
|
||||
|
||||
/// Convert a string into an unsigned integer value
|
||||
extern unsigned int toUInt(const std::string &str);
|
||||
|
||||
/// Convert a string into a floating point value
|
||||
extern float toFloat(const std::string &str);
|
||||
|
||||
/// Convert a string into a 3D vector
|
||||
extern Eigen::Vector3f toVector3f(const std::string &str);
|
||||
|
||||
/// Tokenize a string into a list by splitting at 'delim'
|
||||
extern std::vector<std::string> tokenize(const std::string &s, const std::string &delim = ", ", bool includeEmpty = false);
|
||||
|
||||
/// Check if a string ends with another string
|
||||
extern bool endsWith(const std::string &value, const std::string &ending);
|
||||
|
||||
/// Convert a time value in milliseconds into a human-readable string
|
||||
extern std::string timeString(double time, bool precise = false);
|
||||
|
||||
/// Convert a memory amount in bytes into a human-readable string
|
||||
extern std::string memString(size_t size, bool precise = false);
|
||||
|
||||
/// Measures associated with probability distributions
|
||||
enum EMeasure {
|
||||
EUnknownMeasure = 0,
|
||||
ESolidAngle,
|
||||
EDiscrete
|
||||
};
|
||||
|
||||
//// Convert radians to degrees
|
||||
inline float radToDeg(float value) { return value * (180.0f / M_PI); }
|
||||
|
||||
/// Convert degrees to radians
|
||||
inline float degToRad(float value) { return value * (M_PI / 180.0f); }
|
||||
|
||||
#if !defined(_GNU_SOURCE)
|
||||
/// Emulate sincosf using sinf() and cosf()
|
||||
inline void sincosf(float theta, float *_sin, float *_cos) {
|
||||
*_sin = sinf(theta);
|
||||
*_cos = cosf(theta);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Simple floating point clamping function
|
||||
inline float clamp(float value, float min, float max) {
|
||||
if (value < min)
|
||||
return min;
|
||||
else if (value > max)
|
||||
return max;
|
||||
else return value;
|
||||
}
|
||||
|
||||
/// Simple integer clamping function
|
||||
inline int clamp(int value, int min, int max) {
|
||||
if (value < min)
|
||||
return min;
|
||||
else if (value > max)
|
||||
return max;
|
||||
else return value;
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two values
|
||||
inline float lerp(float t, float v1, float v2) {
|
||||
return ((float) 1 - t) * v1 + t * v2;
|
||||
}
|
||||
|
||||
inline float bilerp(float x, float y, float v1, float v2, float v3, float v4) {
|
||||
return v1*(1.0-x)*(1.0-y)+
|
||||
v2*(x)*(1.0-y)+
|
||||
v3*(1.0-x)*(y)+
|
||||
v4*(x)*(y);
|
||||
}
|
||||
|
||||
/// Always-positive modulo operation
|
||||
inline int mod(int a, int b) {
|
||||
int r = a % b;
|
||||
return (r < 0) ? r+b : r;
|
||||
}
|
||||
|
||||
/// Compute a direction for the given coordinates in spherical coordinates
|
||||
extern Vector3f sphericalDirection(float theta, float phi);
|
||||
|
||||
/// Compute a direction for the given coordinates in spherical coordinates
|
||||
extern Point2f sphericalCoordinates(const Vector3f &dir);
|
||||
|
||||
/**
|
||||
* \brief Calculates the unpolarized fresnel reflection coefficient for a
|
||||
* dielectric material. Handles incidence from either side (i.e.
|
||||
* \code cosThetaI<0 is allowed).
|
||||
*
|
||||
* \param cosThetaI
|
||||
* Cosine of the angle between the normal and the incident ray
|
||||
* \param extIOR
|
||||
* Refractive index of the side that contains the surface normal
|
||||
* \param intIOR
|
||||
* Refractive index of the interior
|
||||
*/
|
||||
extern float fresnel(float cosThetaI, float extIOR, float intIOR);
|
||||
|
||||
/**
|
||||
* \brief Return the global file resolver instance
|
||||
*
|
||||
* This class is used to locate resource files (e.g. mesh or
|
||||
* texture files) referenced by a scene being loaded
|
||||
*/
|
||||
extern filesystem::resolver *getFileResolver();
|
||||
|
||||
NORI_NAMESPACE_END
|
198
cs440-acg/include/nori/dpdf.h
Normal file
198
cs440-acg/include/nori/dpdf.h
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/common.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Discrete probability distribution
|
||||
*
|
||||
* This data structure can be used to transform uniformly distributed
|
||||
* samples to a stored discrete probability distribution.
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
struct DiscretePDF {
|
||||
public:
|
||||
/// Allocate memory for a distribution with the given number of entries
|
||||
explicit DiscretePDF(size_t nEntries = 0) {
|
||||
reserve(nEntries);
|
||||
clear();
|
||||
}
|
||||
|
||||
/// Clear all entries
|
||||
void clear() {
|
||||
m_cdf.clear();
|
||||
m_cdf.push_back(0.0f);
|
||||
m_normalized = false;
|
||||
}
|
||||
|
||||
/// Reserve memory for a certain number of entries
|
||||
void reserve(size_t nEntries) {
|
||||
m_cdf.reserve(nEntries+1);
|
||||
}
|
||||
|
||||
/// Append an entry with the specified discrete probability
|
||||
void append(float pdfValue) {
|
||||
m_cdf.push_back(m_cdf[m_cdf.size()-1] + pdfValue);
|
||||
}
|
||||
|
||||
/// Return the number of entries so far
|
||||
size_t size() const {
|
||||
return m_cdf.size()-1;
|
||||
}
|
||||
|
||||
/// Access an entry by its index
|
||||
float operator[](size_t entry) const {
|
||||
return m_cdf[entry+1] - m_cdf[entry];
|
||||
}
|
||||
|
||||
/// Have the probability densities been normalized?
|
||||
bool isNormalized() const {
|
||||
return m_normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the original (unnormalized) sum of all PDF entries
|
||||
*
|
||||
* This assumes that \ref normalize() has previously been called
|
||||
*/
|
||||
float getSum() const {
|
||||
return m_sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the normalization factor (i.e. the inverse of \ref getSum())
|
||||
*
|
||||
* This assumes that \ref normalize() has previously been called
|
||||
*/
|
||||
float getNormalization() const {
|
||||
return m_normalization;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Normalize the distribution
|
||||
*
|
||||
* \return Sum of the (previously unnormalized) entries
|
||||
*/
|
||||
float normalize() {
|
||||
m_sum = m_cdf[m_cdf.size()-1];
|
||||
if (m_sum > 0) {
|
||||
m_normalization = 1.0f / m_sum;
|
||||
for (size_t i=1; i<m_cdf.size(); ++i)
|
||||
m_cdf[i] *= m_normalization;
|
||||
m_cdf[m_cdf.size()-1] = 1.0f;
|
||||
m_normalized = true;
|
||||
} else {
|
||||
m_normalization = 0.0f;
|
||||
}
|
||||
return m_sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief %Transform a uniformly distributed sample to the stored distribution
|
||||
*
|
||||
* \param[in] sampleValue
|
||||
* An uniformly distributed sample on [0,1]
|
||||
* \return
|
||||
* The discrete index associated with the sample
|
||||
*/
|
||||
size_t sample(float sampleValue) const {
|
||||
std::vector<float>::const_iterator entry =
|
||||
std::lower_bound(m_cdf.begin(), m_cdf.end(), sampleValue);
|
||||
size_t index = (size_t) std::max((ptrdiff_t) 0, entry - m_cdf.begin() - 1);
|
||||
return std::min(index, m_cdf.size()-2);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief %Transform a uniformly distributed sample to the stored distribution
|
||||
*
|
||||
* \param[in] sampleValue
|
||||
* An uniformly distributed sample on [0,1]
|
||||
* \param[out] pdf
|
||||
* Probability value of the sample
|
||||
* \return
|
||||
* The discrete index associated with the sample
|
||||
*/
|
||||
size_t sample(float sampleValue, float &pdf) const {
|
||||
size_t index = sample(sampleValue);
|
||||
pdf = operator[](index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief %Transform a uniformly distributed sample to the stored distribution
|
||||
*
|
||||
* The original sample is value adjusted so that it can be "reused".
|
||||
*
|
||||
* \param[in, out] sampleValue
|
||||
* An uniformly distributed sample on [0,1]
|
||||
* \return
|
||||
* The discrete index associated with the sample
|
||||
*/
|
||||
size_t sampleReuse(float &sampleValue) const {
|
||||
size_t index = sample(sampleValue);
|
||||
sampleValue = (sampleValue - m_cdf[index])
|
||||
/ (m_cdf[index + 1] - m_cdf[index]);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief %Transform a uniformly distributed sample.
|
||||
*
|
||||
* The original sample is value adjusted so that it can be "reused".
|
||||
*
|
||||
* \param[in,out]
|
||||
* An uniformly distributed sample on [0,1]
|
||||
* \param[out] pdf
|
||||
* Probability value of the sample
|
||||
* \return
|
||||
* The discrete index associated with the sample
|
||||
*/
|
||||
size_t sampleReuse(float &sampleValue, float &pdf) const {
|
||||
size_t index = sample(sampleValue, pdf);
|
||||
sampleValue = (sampleValue - m_cdf[index])
|
||||
/ (m_cdf[index + 1] - m_cdf[index]);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Turn the underlying distribution into a
|
||||
* human-readable string format
|
||||
*/
|
||||
std::string toString() const {
|
||||
std::string result = tfm::format("DiscretePDF[sum=%f, "
|
||||
"normalized=%f, pdf = {", m_sum, m_normalized);
|
||||
|
||||
for (size_t i=0; i<m_cdf.size(); ++i) {
|
||||
result += std::to_string(operator[](i));
|
||||
if (i != m_cdf.size()-1)
|
||||
result += ", ";
|
||||
}
|
||||
return result + "}]";
|
||||
}
|
||||
private:
|
||||
std::vector<float> m_cdf;
|
||||
float m_sum, m_normalization;
|
||||
bool m_normalized;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
71
cs440-acg/include/nori/emitter.h
Normal file
71
cs440-acg/include/nori/emitter.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/object.h>
|
||||
#include <nori/mesh.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Superclass of all emitters
|
||||
*/
|
||||
class Emitter : public NoriObject {
|
||||
public:
|
||||
|
||||
//Sample Emitters without Mesh attached
|
||||
virtual Color3f samplePosition(const Point2f &s, EmitterSample& es) const {return Color3f();};
|
||||
|
||||
/**
|
||||
* \brief Sample the Emiter
|
||||
*
|
||||
* \param scene Scene
|
||||
* \param p position
|
||||
* \param lp light position
|
||||
* \param ln light normal
|
||||
* \param pdf_dir direction of the PDF
|
||||
* \param sample A uniformly distributed sample on \f$[0,1]^2\f$
|
||||
*
|
||||
* \return Color value
|
||||
*/
|
||||
virtual Color3f sample(const Scene *scene, EmitterSample& es) const = 0;
|
||||
|
||||
/**
|
||||
* \brief Returns the Color evaluated using the light normal and the light to interection path
|
||||
*
|
||||
* \param its light intersection
|
||||
*/
|
||||
virtual Color3f eval(const Intersection &its) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns the PDF using the light normal and the light to interection path
|
||||
* \param lti ray
|
||||
*/
|
||||
virtual float pdf(const Vector3f <i) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Return the type of object (i.e. Mesh/Emitter/etc.)
|
||||
* provided by this instance
|
||||
* */
|
||||
EClassType getClassType() const { return EEmitter; }
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
147
cs440-acg/include/nori/frame.h
Normal file
147
cs440-acg/include/nori/frame.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/vector.h>
|
||||
|
||||
NORI_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, ..).
|
||||
*/
|
||||
struct Frame {
|
||||
Vector3f s, t;
|
||||
Normal3f n;
|
||||
|
||||
/// Default constructor -- performs no initialization!
|
||||
Frame() { }
|
||||
|
||||
/// Given a normal and tangent vectors, construct a new coordinate frame
|
||||
Frame(const Vector3f &s, const Vector3f &t, const Normal3f &n)
|
||||
: s(s), t(t), n(n) { }
|
||||
|
||||
/// Construct a frame from the given orthonormal vectors
|
||||
Frame(const Vector3f &x, const Vector3f &y, const Vector3f &z)
|
||||
: s(x), t(y), n(z) { }
|
||||
|
||||
/// Construct a new coordinate frame from a single vector
|
||||
Frame(const Vector3f &n) : n(n) {
|
||||
coordinateSystem(n, s, t);
|
||||
}
|
||||
|
||||
/// Convert from world coordinates to local coordinates
|
||||
Vector3f toLocal(const Vector3f &v) const {
|
||||
return Vector3f(
|
||||
v.dot(s), v.dot(t), v.dot(n)
|
||||
);
|
||||
}
|
||||
|
||||
/// Convert from local coordinates to world coordinates
|
||||
Vector3f toWorld(const Vector3f &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 cosine of the angle between the normal and v */
|
||||
static float cosTheta(const Vector3f &v) {
|
||||
return 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 */
|
||||
static float sinTheta(const Vector3f &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 */
|
||||
static float tanTheta(const Vector3f &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 sine of the angle between the normal and v */
|
||||
static float sinTheta2(const Vector3f &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 phi parameter in spherical coordinates */
|
||||
static float sinPhi(const Vector3f &v) {
|
||||
float sinTheta = Frame::sinTheta(v);
|
||||
if (sinTheta == 0.0f)
|
||||
return 1.0f;
|
||||
return clamp(v.y() / sinTheta, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
/** \brief Assuming that the given direction is in the local coordinate
|
||||
* system, return the cosine of the phi parameter in spherical coordinates */
|
||||
static float cosPhi(const Vector3f &v) {
|
||||
float sinTheta = Frame::sinTheta(v);
|
||||
if (sinTheta == 0.0f)
|
||||
return 1.0f;
|
||||
return clamp(v.x() / sinTheta, -1.0f, 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 */
|
||||
static float sinPhi2(const Vector3f &v) {
|
||||
return clamp(v.y() * v.y() / sinTheta2(v), 0.0f, 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 */
|
||||
static float cosPhi2(const Vector3f &v) {
|
||||
return clamp(v.x() * v.x() / sinTheta2(v), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/// Equality test
|
||||
bool operator==(const Frame &frame) const {
|
||||
return frame.s == s && frame.t == t && frame.n == n;
|
||||
}
|
||||
|
||||
/// Inequality test
|
||||
bool operator!=(const Frame &frame) const {
|
||||
return !operator==(frame);
|
||||
}
|
||||
|
||||
/// Return a human-readable string summary of this frame
|
||||
std::string toString() const {
|
||||
return tfm::format(
|
||||
"Frame[\n"
|
||||
" s = %s,\n"
|
||||
" t = %s,\n"
|
||||
" n = %s\n"
|
||||
"]", s.toString(), t.toString(), n.toString());
|
||||
}
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
38
cs440-acg/include/nori/gui.h
Normal file
38
cs440-acg/include/nori/gui.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/common.h>
|
||||
#include <nanogui/screen.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
class NoriScreen : public nanogui::Screen {
|
||||
public:
|
||||
NoriScreen(const ImageBlock &block);
|
||||
void draw_contents() override;
|
||||
private:
|
||||
const ImageBlock &m_block;
|
||||
nanogui::ref<nanogui::Shader> m_shader;
|
||||
nanogui::ref<nanogui::Texture> m_texture;
|
||||
nanogui::ref<nanogui::RenderPass> m_renderPass;
|
||||
float m_scale = 1.f;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
63
cs440-acg/include/nori/integrator.h
Normal file
63
cs440-acg/include/nori/integrator.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/object.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Abstract integrator (i.e. a rendering technique)
|
||||
*
|
||||
* In Nori, the different rendering techniques are collectively referred to as
|
||||
* integrators, since they perform integration over a high-dimensional
|
||||
* space. Each integrator represents a specific approach for solving
|
||||
* the light transport equation---usually favored in certain scenarios, but
|
||||
* at the same time affected by its own set of intrinsic limitations.
|
||||
*/
|
||||
class Integrator : public NoriObject {
|
||||
public:
|
||||
/// Release all memory
|
||||
virtual ~Integrator() { }
|
||||
|
||||
/// Perform an (optional) preprocess step
|
||||
virtual void preprocess(const Scene *scene) { }
|
||||
|
||||
/**
|
||||
* \brief Sample the incident radiance along a ray
|
||||
*
|
||||
* \param scene
|
||||
* A pointer to the underlying scene
|
||||
* \param sampler
|
||||
* A pointer to a sample generator
|
||||
* \param ray
|
||||
* The ray in question
|
||||
* \return
|
||||
* A (usually) unbiased estimate of the radiance in this direction
|
||||
*/
|
||||
virtual Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const = 0;
|
||||
|
||||
/**
|
||||
* \brief Return the type of object (i.e. Mesh/BSDF/etc.)
|
||||
* provided by this instance
|
||||
* */
|
||||
EClassType getClassType() const { return EIntegrator; }
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
213
cs440-acg/include/nori/mesh.h
Normal file
213
cs440-acg/include/nori/mesh.h
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/object.h>
|
||||
#include <nori/frame.h>
|
||||
#include <nori/bbox.h>
|
||||
#include <nori/dpdf.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
struct EmitterSample{
|
||||
Vector3f o;
|
||||
Vector3f p;
|
||||
Vector3f n;
|
||||
Vector3f dir;
|
||||
float dist;
|
||||
float pdf=1.0;
|
||||
Point2f uv;
|
||||
|
||||
EmitterSample(Vector3f& p, Vector3f& n, Vector3f& dir, float dist, float pdf, Point2f& uv):
|
||||
p(p),n(n),dir(dir),dist(dist),pdf(pdf),uv(uv){};
|
||||
EmitterSample(){};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Intersection data structure
|
||||
*
|
||||
* This data structure records local information about a ray-triangle intersection.
|
||||
* This includes the position, traveled ray distance, uv coordinates, as well
|
||||
* as well as two local coordinate frames (one that corresponds to the true
|
||||
* geometry, and one that is used for shading computations).
|
||||
*/
|
||||
struct Intersection {
|
||||
/// Position of the surface intersection
|
||||
Point3f p;
|
||||
/// Unoccluded distance along the ray
|
||||
float t;
|
||||
/// Ray WI (input vector)
|
||||
Vector3f wi;
|
||||
/// UV coordinates, if any
|
||||
Point2f uv;
|
||||
/// Shading frame (based on the shading normal)
|
||||
Frame shFrame;
|
||||
/// Geometric frame (based on the true geometry)
|
||||
Frame geoFrame;
|
||||
/// Pointer to the associated mesh
|
||||
const Mesh *mesh;
|
||||
|
||||
/// Create an uninitialized intersection record
|
||||
Intersection() : mesh(nullptr) { }
|
||||
|
||||
/// Transform a direction vector into the local shading frame
|
||||
Vector3f toLocal(const Vector3f &d) const {
|
||||
return shFrame.toLocal(d);
|
||||
}
|
||||
|
||||
/// Transform a direction vector from local to world coordinates
|
||||
Vector3f toWorld(const Vector3f &d) const {
|
||||
return shFrame.toWorld(d);
|
||||
}
|
||||
|
||||
/// Return a human-readable summary of the intersection record
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Triangle mesh
|
||||
*
|
||||
* This class stores a triangle mesh object and provides numerous functions
|
||||
* for querying the individual triangles. Subclasses of \c Mesh implement
|
||||
* the specifics of how to create its contents (e.g. by loading from an
|
||||
* external file)
|
||||
*/
|
||||
class Mesh : public NoriObject {
|
||||
public:
|
||||
/// Release all memory
|
||||
virtual ~Mesh();
|
||||
|
||||
/// Initialize internal data structures (called once by the XML parser)
|
||||
virtual void activate();
|
||||
|
||||
/// Return the total number of triangles in this shape
|
||||
uint32_t getTriangleCount() const { return (uint32_t) m_F.cols(); }
|
||||
|
||||
/// Return the total number of vertices in this shape
|
||||
uint32_t getVertexCount() const { return (uint32_t) m_V.cols(); }
|
||||
|
||||
/// Return the surface area of the given triangle
|
||||
float surfaceArea(uint32_t index) const;
|
||||
|
||||
//// Return an axis-aligned bounding box of the entire mesh
|
||||
const BoundingBox3f &getBoundingBox() const { return m_bbox; }
|
||||
|
||||
//// Return an axis-aligned bounding box containing the given triangle
|
||||
BoundingBox3f getBoundingBox(uint32_t index) const;
|
||||
|
||||
//// Return the centroid of the given triangle
|
||||
Point3f getCentroid(uint32_t index) const;
|
||||
|
||||
/** \brief Ray-triangle intersection test
|
||||
*
|
||||
* Uses the algorithm by Moeller and Trumbore discussed at
|
||||
* <tt>http://www.acm.org/jgt/papers/MollerTrumbore97/code.html</tt>.
|
||||
*
|
||||
* Note that the test only applies to a single triangle in the mesh.
|
||||
* An acceleration data structure like \ref BVH is needed to search
|
||||
* for intersections against many triangles.
|
||||
*
|
||||
* \param index
|
||||
* Index of the triangle that should be intersected
|
||||
* \param ray
|
||||
* The ray segment to be used for the intersection query
|
||||
* \param t
|
||||
* Upon success, \a t contains the distance from the ray origin to the
|
||||
* intersection point,
|
||||
* \param u
|
||||
* Upon success, \c u will contain the 'U' component of the intersection
|
||||
* in barycentric coordinates
|
||||
* \param v
|
||||
* Upon success, \c v will contain the 'V' component of the intersection
|
||||
* in barycentric coordinates
|
||||
* \return
|
||||
* \c true if an intersection has been detected
|
||||
*/
|
||||
bool rayIntersect(uint32_t index, const Ray3f &ray, float &u, float &v, float &t) const;
|
||||
|
||||
/*
|
||||
* \brief Uniform Sampling for a position on the mesh
|
||||
*
|
||||
* \param s SamplePoint
|
||||
* \param es EmitterSample
|
||||
*/
|
||||
void samplePosition(const Point2f &s, EmitterSample& es) const;
|
||||
|
||||
/// Return a pointer to the vertex positions
|
||||
const MatrixXf &getVertexPositions() const { return m_V; }
|
||||
|
||||
/// Return a pointer to the vertex normals (or \c nullptr if there are none)
|
||||
const MatrixXf &getVertexNormals() const { return m_N; }
|
||||
|
||||
/// Return a pointer to the texture coordinates (or \c nullptr if there are none)
|
||||
const MatrixXf &getVertexTexCoords() const { return m_UV; }
|
||||
|
||||
/// Return a pointer to the triangle vertex index list
|
||||
const MatrixXu &getIndices() const { return m_F; }
|
||||
|
||||
/// Is this mesh an area emitter?
|
||||
bool isEmitter() const { return m_emitter != nullptr; }
|
||||
|
||||
/// Return a pointer to an attached area emitter instance
|
||||
Emitter *getEmitter() { return m_emitter; }
|
||||
|
||||
/// Return a pointer to an attached area emitter instance (const version)
|
||||
const Emitter *getEmitter() const { return m_emitter; }
|
||||
|
||||
/// Return a pointer to the BSDF associated with this mesh
|
||||
const BSDF *getBSDF() const { return m_bsdf; }
|
||||
|
||||
/// Return DPDF Normalization factor
|
||||
float getDPDFNormalization() const { return m_dpdf->getNormalization(); }
|
||||
|
||||
/// Register a child object (e.g. a BSDF) with the mesh
|
||||
virtual void addChild(NoriObject *child);
|
||||
|
||||
/// Return the name of this mesh
|
||||
const std::string &getName() const { return m_name; }
|
||||
|
||||
/// Return a human-readable summary of this instance
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* \brief Return the type of object (i.e. Mesh/BSDF/etc.)
|
||||
* provided by this instance
|
||||
* */
|
||||
EClassType getClassType() const { return EMesh; }
|
||||
|
||||
protected:
|
||||
/// Create an empty mesh
|
||||
Mesh();
|
||||
|
||||
protected:
|
||||
std::string m_name; ///< Identifying name
|
||||
MatrixXf m_V; ///< Vertex positions
|
||||
MatrixXf m_N; ///< Vertex normals
|
||||
MatrixXf m_UV; ///< Vertex texture coordinates
|
||||
MatrixXu m_F; ///< Faces
|
||||
BSDF *m_bsdf = nullptr; ///< BSDF of the surface
|
||||
DiscretePDF *m_dpdf = nullptr; ///< DPDF
|
||||
Emitter *m_emitter = nullptr; ///< Associated emitter, if any
|
||||
BoundingBox3f m_bbox; ///< Bounding box of the mesh
|
||||
float m_surface_total; ///< Surface Total
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
58
cs440-acg/include/nori/mipmap.h
Normal file
58
cs440-acg/include/nori/mipmap.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/warp.h>
|
||||
#include <nori/bitmap.h>
|
||||
#include <map>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief MIPMAP Class
|
||||
*/
|
||||
struct Mipmap {
|
||||
public:
|
||||
|
||||
Mipmap(){};
|
||||
Mipmap(const std::string &filename);
|
||||
|
||||
float get(size_t x, size_t y, size_t size) const;
|
||||
|
||||
Color3f getColor(float x, float y) const;
|
||||
|
||||
size_t getSize() const {
|
||||
return m_size;
|
||||
}
|
||||
float getPDFF() const {
|
||||
return m_size*m_size;
|
||||
}
|
||||
|
||||
private:
|
||||
Bitmap m_img;
|
||||
size_t m_size;
|
||||
float* m_mm;
|
||||
float m_maxv;
|
||||
std::map<size_t,float*> m_stp;
|
||||
|
||||
void fill_mm(size_t size);
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
164
cs440-acg/include/nori/object.h
Normal file
164
cs440-acg/include/nori/object.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/proplist.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Base class of all objects
|
||||
*
|
||||
* A Nori object represents an instance that is part of
|
||||
* a scene description, e.g. a scattering model or emitter.
|
||||
*/
|
||||
class NoriObject {
|
||||
public:
|
||||
enum EClassType {
|
||||
EScene = 0,
|
||||
EMesh,
|
||||
EBSDF,
|
||||
EPhaseFunction,
|
||||
EEmitter,
|
||||
EMedium,
|
||||
ECamera,
|
||||
EIntegrator,
|
||||
ESampler,
|
||||
ETest,
|
||||
ETexture,
|
||||
EReconstructionFilter,
|
||||
EClassTypeCount
|
||||
};
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~NoriObject() { }
|
||||
|
||||
/**
|
||||
* \brief Return the type of object (i.e. Mesh/BSDF/etc.)
|
||||
* provided by this instance
|
||||
* */
|
||||
virtual EClassType getClassType() const = 0;
|
||||
|
||||
/**
|
||||
* \brief Add a child object to the current instance
|
||||
*
|
||||
* The default implementation does not support children and
|
||||
* simply throws an exception
|
||||
*/
|
||||
virtual void addChild(NoriObject *child);
|
||||
|
||||
/**
|
||||
* \brief Set the parent object
|
||||
*
|
||||
* Subclasses may choose to override this method to be
|
||||
* notified when they are added to a parent object. The
|
||||
* default implementation does nothing.
|
||||
*/
|
||||
virtual void setParent(NoriObject *parent);
|
||||
|
||||
/**
|
||||
* \brief Perform some action associated with the object
|
||||
*
|
||||
* The default implementation throws an exception. Certain objects
|
||||
* may choose to override it, e.g. to implement initialization,
|
||||
* testing, or rendering functionality.
|
||||
*
|
||||
* This function is called by the XML parser once it has
|
||||
* constructed an object and added all of its children
|
||||
* using \ref addChild().
|
||||
*/
|
||||
virtual void activate();
|
||||
|
||||
/// Return a brief string summary of the instance (for debugging purposes)
|
||||
virtual std::string toString() const = 0;
|
||||
|
||||
/// Turn a class type into a human-readable string
|
||||
static std::string classTypeName(EClassType type) {
|
||||
switch (type) {
|
||||
case EScene: return "scene";
|
||||
case EMesh: return "mesh";
|
||||
case EBSDF: return "bsdf";
|
||||
case EEmitter: return "emitter";
|
||||
case ECamera: return "camera";
|
||||
case EIntegrator: return "integrator";
|
||||
case ESampler: return "sampler";
|
||||
case ETest: return "test";
|
||||
default: return "<unknown>";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Factory for Nori objects
|
||||
*
|
||||
* This utility class is part of a mini-RTTI framework and can
|
||||
* instantiate arbitrary Nori objects by their name.
|
||||
*/
|
||||
class NoriObjectFactory {
|
||||
public:
|
||||
typedef std::function<NoriObject *(const PropertyList &)> Constructor;
|
||||
|
||||
/**
|
||||
* \brief Register an object constructor with the object factory
|
||||
*
|
||||
* This function is called by the macro \ref NORI_REGISTER_CLASS
|
||||
*
|
||||
* \param name
|
||||
* An internal name that is associated with this class. This is the
|
||||
* 'type' field found in the scene description XML files
|
||||
*
|
||||
* \param constr
|
||||
* A function pointer to an anonymous function that is
|
||||
* able to call the constructor of the class.
|
||||
*/
|
||||
static void registerClass(const std::string &name, const Constructor &constr);
|
||||
|
||||
/**
|
||||
* \brief Construct an instance from the class of the given name
|
||||
*
|
||||
* \param name
|
||||
* An internal name that is associated with this class. This is the
|
||||
* 'type' field found in the scene description XML files
|
||||
*
|
||||
* \param propList
|
||||
* A list of properties that will be passed to the constructor
|
||||
* of the class.
|
||||
*/
|
||||
static NoriObject *createInstance(const std::string &name,
|
||||
const PropertyList &propList) {
|
||||
if (!m_constructors || m_constructors->find(name) == m_constructors->end())
|
||||
throw NoriException("A constructor for class \"%s\" could not be found!", name);
|
||||
return (*m_constructors)[name](propList);
|
||||
}
|
||||
private:
|
||||
static std::map<std::string, Constructor> *m_constructors;
|
||||
};
|
||||
|
||||
/// Macro for registering an object constructor with the \ref NoriObjectFactory
|
||||
#define NORI_REGISTER_CLASS(cls, name) \
|
||||
cls *cls ##_create(const PropertyList &list) { \
|
||||
return new cls(list); \
|
||||
} \
|
||||
static struct cls ##_{ \
|
||||
cls ##_() { \
|
||||
NoriObjectFactory::registerClass(name, cls ##_create); \
|
||||
} \
|
||||
} cls ##__NORI_;
|
||||
|
||||
NORI_NAMESPACE_END
|
31
cs440-acg/include/nori/octreenode.h
Normal file
31
cs440-acg/include/nori/octreenode.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <nori/mesh.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
class OctreeNode {
|
||||
public:
|
||||
//Constructor for Internal Node
|
||||
OctreeNode(BoundingBox3f bbox) : m_bbox(bbox) {};
|
||||
|
||||
//Constructor for Leaf Node
|
||||
OctreeNode(BoundingBox3f bbox, std::vector<uint32_t>* triangle_ids) : m_triangle_ids(*triangle_ids), m_bbox(bbox) {};
|
||||
|
||||
//Computes the Statistics of the Octree Node
|
||||
void computeStats(size_t* internal, size_t* leaf, size_t* triangles);
|
||||
|
||||
|
||||
OctreeNode* m_child_nodes[8] = {0}; ///< Child Nodes (Branch)
|
||||
std::vector<uint32_t> m_triangle_ids; ///< Triangle Ids (Leaf)
|
||||
BoundingBox3f m_bbox; ///< Bounding Box
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
//Creates a Octree Node
|
||||
OctreeNode* octreenode_builder(Mesh* mesh, BoundingBox3f bbox, std::vector<uint32_t>* triangle_ids, int depth);
|
||||
|
||||
|
||||
NORI_NAMESPACE_END
|
31
cs440-acg/include/nori/parser.h
Normal file
31
cs440-acg/include/nori/parser.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/object.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Load a scene from the specified filename and
|
||||
* return its root object
|
||||
*/
|
||||
extern NoriObject *loadFromXML(const std::string &filename);
|
||||
|
||||
NORI_NAMESPACE_END
|
139
cs440-acg/include/nori/proplist.h
Normal file
139
cs440-acg/include/nori/proplist.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/color.h>
|
||||
#include <nori/transform.h>
|
||||
#include <map>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief This is an associative container used to supply the constructors
|
||||
* of \ref NoriObject subclasses with parameter information.
|
||||
*/
|
||||
class PropertyList {
|
||||
public:
|
||||
PropertyList() { }
|
||||
|
||||
bool contains(const std::string &name) const;
|
||||
|
||||
/// Set a boolean property
|
||||
void setBoolean(const std::string &name, const bool &value);
|
||||
|
||||
/// Get a boolean property, and throw an exception if it does not exist
|
||||
bool getBoolean(const std::string &name) const;
|
||||
|
||||
/// Get a boolean property, and use a default value if it does not exist
|
||||
bool getBoolean(const std::string &name, const bool &defaultValue) const;
|
||||
|
||||
/// Set an integer property
|
||||
void setInteger(const std::string &name, const int &value);
|
||||
|
||||
/// Get an integer property, and throw an exception if it does not exist
|
||||
int getInteger(const std::string &name) const;
|
||||
|
||||
/// Get am integer property, and use a default value if it does not exist
|
||||
int getInteger(const std::string &name, const int &defaultValue) const;
|
||||
|
||||
/// Set a float property
|
||||
void setFloat(const std::string &name, const float &value);
|
||||
|
||||
/// Get a float property, and throw an exception if it does not exist
|
||||
float getFloat(const std::string &name) const;
|
||||
|
||||
/// Get a float property, and use a default value if it does not exist
|
||||
float getFloat(const std::string &name, const float &defaultValue) const;
|
||||
|
||||
/// Set a string property
|
||||
void setString(const std::string &name, const std::string &value);
|
||||
|
||||
/// Get a string property, and throw an exception if it does not exist
|
||||
std::string getString(const std::string &name) const;
|
||||
|
||||
/// Get a string property, and use a default value if it does not exist
|
||||
std::string getString(const std::string &name, const std::string &defaultValue) const;
|
||||
|
||||
/// Set a color property
|
||||
void setColor(const std::string &name, const Color3f &value);
|
||||
|
||||
/// Get a color property, and throw an exception if it does not exist
|
||||
Color3f getColor(const std::string &name) const;
|
||||
|
||||
/// Get a color property, and use a default value if it does not exist
|
||||
Color3f getColor(const std::string &name, const Color3f &defaultValue) const;
|
||||
|
||||
/// Set a point property
|
||||
void setPoint(const std::string &name, const Point3f &value);
|
||||
|
||||
/// Get a point property, and throw an exception if it does not exist
|
||||
Point3f getPoint(const std::string &name) const;
|
||||
|
||||
/// Get a point property, and use a default value if it does not exist
|
||||
Point3f getPoint(const std::string &name, const Point3f &defaultValue) const;
|
||||
|
||||
/// Set a vector property
|
||||
void setVector(const std::string &name, const Vector3f &value);
|
||||
|
||||
/// Get a vector property, and throw an exception if it does not exist
|
||||
Vector3f getVector(const std::string &name) const;
|
||||
|
||||
/// Get a vector property, and use a default value if it does not exist
|
||||
Vector3f getVector(const std::string &name, const Vector3f &defaultValue) const;
|
||||
|
||||
/// Set a transform property
|
||||
void setTransform(const std::string &name, const Transform &value);
|
||||
|
||||
/// Get a transform property, and throw an exception if it does not exist
|
||||
Transform getTransform(const std::string &name) const;
|
||||
|
||||
/// Get a transform property, and use a default value if it does not exist
|
||||
Transform getTransform(const std::string &name, const Transform &defaultValue) const;
|
||||
private:
|
||||
/* Custom variant data type (stores one of boolean/integer/float/...) */
|
||||
struct Property {
|
||||
enum {
|
||||
boolean_type, integer_type, float_type,
|
||||
string_type, color_type, point_type,
|
||||
vector_type, transform_type
|
||||
} type;
|
||||
|
||||
/* Visual studio lacks support for unrestricted unions (as of ver. 2013) */
|
||||
struct Value
|
||||
{
|
||||
Value() : boolean_value(false) { }
|
||||
~Value() { }
|
||||
|
||||
bool boolean_value;
|
||||
int integer_value;
|
||||
float float_value;
|
||||
std::string string_value;
|
||||
Color3f color_value;
|
||||
Point3f point_value;
|
||||
Vector3f vector_value;
|
||||
Transform transform_value;
|
||||
} value;
|
||||
|
||||
Property() : type(boolean_type) { }
|
||||
};
|
||||
|
||||
std::map<std::string, Property> m_properties;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
101
cs440-acg/include/nori/ray.h
Normal file
101
cs440-acg/include/nori/ray.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/vector.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Simple n-dimensional ray segment data structure
|
||||
*
|
||||
* Along with the ray origin and direction, this data structure additionally
|
||||
* stores a ray segment [mint, maxt] (whose entries may include positive/negative
|
||||
* infinity), as well as the componentwise reciprocals of the ray direction.
|
||||
* That is just done for convenience, as these values are frequently required.
|
||||
*
|
||||
* \remark Important: be careful when changing the ray direction. You must
|
||||
* call \ref update() to compute the componentwise reciprocals as well, or Nori's
|
||||
* ray-triangle intersection code will go haywire.
|
||||
*/
|
||||
template <typename _PointType, typename _VectorType> struct TRay {
|
||||
typedef _PointType PointType;
|
||||
typedef _VectorType VectorType;
|
||||
typedef typename PointType::Scalar Scalar;
|
||||
|
||||
PointType o; ///< Ray origin
|
||||
VectorType d; ///< Ray direction
|
||||
VectorType dRcp; ///< Componentwise reciprocals of the ray direction
|
||||
Scalar mint; ///< Minimum position on the ray segment
|
||||
Scalar maxt; ///< Maximum position on the ray segment
|
||||
|
||||
/// Construct a new ray
|
||||
TRay() : mint(Epsilon),
|
||||
maxt(std::numeric_limits<Scalar>::infinity()) { }
|
||||
|
||||
/// Construct a new ray
|
||||
TRay(const PointType &o, const VectorType &d) : o(o), d(d),
|
||||
mint(Epsilon), maxt(std::numeric_limits<Scalar>::infinity()) {
|
||||
update();
|
||||
}
|
||||
|
||||
/// Construct a new ray
|
||||
TRay(const PointType &o, const VectorType &d,
|
||||
Scalar mint, Scalar maxt) : o(o), d(d), mint(mint), maxt(maxt) {
|
||||
update();
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
TRay(const TRay &ray)
|
||||
: o(ray.o), d(ray.d), dRcp(ray.dRcp),
|
||||
mint(ray.mint), maxt(ray.maxt) { }
|
||||
|
||||
/// Copy a ray, but change the covered segment of the copy
|
||||
TRay(const TRay &ray, Scalar mint, Scalar maxt)
|
||||
: o(ray.o), d(ray.d), dRcp(ray.dRcp), mint(mint), maxt(maxt) { }
|
||||
|
||||
/// Update the reciprocal ray directions after changing 'd'
|
||||
void update() {
|
||||
dRcp = d.cwiseInverse();
|
||||
}
|
||||
|
||||
/// Return the position of a point along the ray
|
||||
PointType operator() (Scalar t) const { return o + t * d; }
|
||||
|
||||
/// Return a ray that points into the opposite direction
|
||||
TRay reverse() const {
|
||||
TRay result;
|
||||
result.o = o; result.d = -d; result.dRcp = -dRcp;
|
||||
result.mint = mint; result.maxt = maxt;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Return a human-readable string summary of this ray
|
||||
std::string toString() const {
|
||||
return tfm::format(
|
||||
"Ray[\n"
|
||||
" o = %s,\n"
|
||||
" d = %s,\n"
|
||||
" mint = %f,\n"
|
||||
" maxt = %f\n"
|
||||
"]", o.toString(), d.toString(), mint, maxt);
|
||||
}
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
57
cs440-acg/include/nori/rfilter.h
Normal file
57
cs440-acg/include/nori/rfilter.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/object.h>
|
||||
|
||||
/// Reconstruction filters will be tabulated at this resolution
|
||||
#define NORI_FILTER_RESOLUTION 32
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Generic radially symmetric image reconstruction filter
|
||||
*
|
||||
* When adding radiance-valued samples to the rendered image, Nori
|
||||
* first convolves them with a so-called image reconstruction filter.
|
||||
*
|
||||
* To learn more about reconstruction filters and sampling theory
|
||||
* in general, take a look at the excellenent chapter 7 of PBRT,
|
||||
* which is freely available at:
|
||||
*
|
||||
* http://graphics.stanford.edu/~mmp/chapters/pbrt_chapter7.pdf
|
||||
*/
|
||||
class ReconstructionFilter : public NoriObject {
|
||||
public:
|
||||
/// Return the filter radius in fractional pixels
|
||||
float getRadius() const { return m_radius; }
|
||||
|
||||
/// Evaluate the filter function
|
||||
virtual float eval(float x) const = 0;
|
||||
|
||||
/**
|
||||
* \brief Return the type of object (i.e. Mesh/Camera/etc.)
|
||||
* provided by this instance
|
||||
* */
|
||||
EClassType getClassType() const { return EReconstructionFilter; }
|
||||
protected:
|
||||
float m_radius;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
109
cs440-acg/include/nori/sampler.h
Normal file
109
cs440-acg/include/nori/sampler.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/object.h>
|
||||
#include <memory>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
class ImageBlock;
|
||||
|
||||
/**
|
||||
* \brief Abstract sample generator
|
||||
*
|
||||
* A sample generator is responsible for generating the random number stream
|
||||
* that will be passed an \ref Integrator implementation as it computes the
|
||||
* radiance incident along a specified ray.
|
||||
*
|
||||
* The most simple conceivable sample generator is just a wrapper around the
|
||||
* Mersenne-Twister random number generator and is implemented in
|
||||
* <tt>independent.cpp</tt> (it is named this way because it generates
|
||||
* statistically independent random numbers).
|
||||
*
|
||||
* Fancier samplers might use stratification or low-discrepancy sequences
|
||||
* (e.g. Halton, Hammersley, or Sobol point sets) for improved convergence.
|
||||
* Another use of this class is in producing intentionally correlated
|
||||
* random numbers, e.g. as part of a Metropolis-Hastings integration scheme.
|
||||
*
|
||||
* The general interface between a sampler and a rendering algorithm is as
|
||||
* follows: Before beginning to render a pixel, the rendering algorithm calls
|
||||
* \ref generate(). The first pixel sample can now be computed, after which
|
||||
* \ref advance() needs to be invoked. This repeats until all pixel samples have
|
||||
* been exhausted. While computing a pixel sample, the rendering
|
||||
* algorithm requests (pseudo-) random numbers using the \ref next1D() and
|
||||
* \ref next2D() functions.
|
||||
*
|
||||
* Conceptually, the right way of thinking of this goes as follows:
|
||||
* For each sample in a pixel, a sample generator produces a (hypothetical)
|
||||
* point in an infinite dimensional random number hypercube. A rendering
|
||||
* algorithm can then request subsequent 1D or 2D components of this point
|
||||
* using the \ref next1D() and \ref next2D() functions. Fancy implementations
|
||||
* of this class make certain guarantees about the stratification of the
|
||||
* first n components with respect to the other points that are sampled
|
||||
* within a pixel.
|
||||
*/
|
||||
class Sampler : public NoriObject {
|
||||
public:
|
||||
/// Release all memory
|
||||
virtual ~Sampler() { }
|
||||
|
||||
/// Create an exact clone of the current instance
|
||||
virtual std::unique_ptr<Sampler> clone() const = 0;
|
||||
|
||||
/**
|
||||
* \brief Prepare to render a new image block
|
||||
*
|
||||
* This function is called when the sampler begins rendering
|
||||
* a new image block. This can be used to deterministically
|
||||
* initialize the sampler so that repeated program runs
|
||||
* always create the same image.
|
||||
*/
|
||||
virtual void prepare(const ImageBlock &block) = 0;
|
||||
|
||||
/**
|
||||
* \brief Prepare to generate new samples
|
||||
*
|
||||
* This function is called initially and every time the
|
||||
* integrator starts rendering a new pixel.
|
||||
*/
|
||||
virtual void generate() = 0;
|
||||
|
||||
/// Advance to the next sample
|
||||
virtual void advance() = 0;
|
||||
|
||||
/// Retrieve the next component value from the current sample
|
||||
virtual float next1D() = 0;
|
||||
|
||||
/// Retrieve the next two component values from the current sample
|
||||
virtual Point2f next2D() = 0;
|
||||
|
||||
/// Return the number of configured pixel samples
|
||||
virtual size_t getSampleCount() const { return m_sampleCount; }
|
||||
|
||||
/**
|
||||
* \brief Return the type of object (i.e. Mesh/Sampler/etc.)
|
||||
* provided by this instance
|
||||
* */
|
||||
EClassType getClassType() const { return ESampler; }
|
||||
protected:
|
||||
size_t m_sampleCount;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
144
cs440-acg/include/nori/scene.h
Normal file
144
cs440-acg/include/nori/scene.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/accel.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Main scene data structure
|
||||
*
|
||||
* This class holds information on scene objects and is responsible for
|
||||
* coordinating rendering jobs. It also provides useful query routines that
|
||||
* are mostly used by the \ref Integrator implementations.
|
||||
*/
|
||||
class Scene : public NoriObject {
|
||||
public:
|
||||
/// Construct a new scene object
|
||||
Scene(const PropertyList &);
|
||||
|
||||
/// Release all memory
|
||||
virtual ~Scene();
|
||||
|
||||
/// Return a pointer to the scene's kd-tree
|
||||
const Accel *getAccel() const { return m_accel; }
|
||||
|
||||
/// Return a pointer to the scene's integrator
|
||||
const Integrator *getIntegrator() const { return m_integrator; }
|
||||
|
||||
/// Return a pointer to the scene's integrator
|
||||
Integrator *getIntegrator() { return m_integrator; }
|
||||
|
||||
/// Return a pointer to the scene's camera
|
||||
const Camera *getCamera() const { return m_camera; }
|
||||
|
||||
/// Return a pointer to the scene's sample generator (const version)
|
||||
const Sampler *getSampler() const { return m_sampler; }
|
||||
|
||||
/// Return a pointer to the scene's sample generator
|
||||
Sampler *getSampler() { return m_sampler; }
|
||||
|
||||
/// Return a reference to an array containing all meshes
|
||||
const std::vector<Mesh *> &getMeshes() const { return m_meshes; }
|
||||
|
||||
/**
|
||||
* \brief Intersect a ray against all triangles stored in the scene
|
||||
* and return detailed intersection information
|
||||
*
|
||||
* \param ray
|
||||
* A 3-dimensional ray data structure with minimum/maximum
|
||||
* extent information
|
||||
*
|
||||
* \param its
|
||||
* A detailed intersection record, which will be filled by the
|
||||
* intersection query
|
||||
*
|
||||
* \return \c true if an intersection was found
|
||||
*/
|
||||
bool rayIntersect(const Ray3f &ray, Intersection &its) const {
|
||||
return m_accel->rayIntersect(ray, its, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Intersect a ray against all triangles stored in the scene
|
||||
* and \a only determine whether or not there is an intersection.
|
||||
*
|
||||
* This method much faster than the other ray tracing function,
|
||||
* but the performance comes at the cost of not providing any
|
||||
* additional information about the detected intersection
|
||||
* (not even its position).
|
||||
*
|
||||
* \param ray
|
||||
* A 3-dimensional ray data structure with minimum/maximum
|
||||
* extent information
|
||||
*
|
||||
* \return \c true if an intersection was found
|
||||
*/
|
||||
bool rayIntersect(const Ray3f &ray) const {
|
||||
Intersection its; /* Unused */
|
||||
return m_accel->rayIntersect(ray, its, true);
|
||||
}
|
||||
|
||||
/// \brief Return an axis-aligned box that bounds the scene
|
||||
const BoundingBox3f &getBoundingBox() const {
|
||||
return m_accel->getBoundingBox();
|
||||
}
|
||||
|
||||
const std::pair<Emitter*,Mesh*> getRandomEmitter(float rnd) const {
|
||||
if(m_emp.size() <=0) return std::pair<Emitter*,Mesh*>(nullptr,nullptr);
|
||||
auto const & n = m_emp.size();
|
||||
size_t index = std::min(static_cast<size_t>(std::floor(n*rnd)),n-1);
|
||||
return m_emp[index];
|
||||
}
|
||||
float getEmitterPDF() const {
|
||||
if(m_emp.size() <=0) return 0.0;
|
||||
return 1.0/m_emp.size();
|
||||
}
|
||||
|
||||
const Emitter* getEmitterEnv() const {
|
||||
return m_emenv;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Inherited from \ref NoriObject::activate()
|
||||
*
|
||||
* Initializes the internal data structures (kd-tree,
|
||||
* emitter sampling data structures, etc.)
|
||||
*/
|
||||
void activate();
|
||||
|
||||
/// Add a child object to the scene (meshes, integrators etc.)
|
||||
void addChild(NoriObject *obj);
|
||||
|
||||
/// Return a string summary of the scene (for debugging purposes)
|
||||
std::string toString() const;
|
||||
|
||||
EClassType getClassType() const { return EScene; }
|
||||
private:
|
||||
std::vector<Mesh *> m_meshes;
|
||||
std::vector<std::pair<Emitter*,Mesh*>> m_emp;
|
||||
Emitter* m_emenv = nullptr;
|
||||
Integrator *m_integrator = nullptr;
|
||||
Sampler *m_sampler = nullptr;
|
||||
Camera *m_camera = nullptr;
|
||||
Accel *m_accel = nullptr;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
14
cs440-acg/include/nori/texture.h
Normal file
14
cs440-acg/include/nori/texture.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <nori/object.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
class Texture : public NoriObject {
|
||||
public:
|
||||
virtual Color3f eval(const Point2f & uv) { return Color3f(); };
|
||||
|
||||
EClassType getClassType() const { return ETexture; }
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
67
cs440-acg/include/nori/timer.h
Normal file
67
cs440-acg/include/nori/timer.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/common.h>
|
||||
#include <chrono>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Simple timer with millisecond precision
|
||||
*
|
||||
* This class is convenient for collecting performance data
|
||||
*/
|
||||
class Timer {
|
||||
public:
|
||||
/// Create a new timer and reset it
|
||||
Timer() { reset(); }
|
||||
|
||||
/// Reset the timer to the current time
|
||||
void reset() { start = std::chrono::system_clock::now(); }
|
||||
|
||||
/// Return the number of milliseconds elapsed since the timer was last reset
|
||||
double elapsed() const {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
|
||||
return (double) duration.count();
|
||||
}
|
||||
|
||||
/// Like \ref elapsed(), but return a human-readable string
|
||||
std::string elapsedString(bool precise = false) const {
|
||||
return timeString(elapsed(), precise);
|
||||
}
|
||||
|
||||
/// Return the number of milliseconds elapsed since the timer was last reset and then reset it
|
||||
double lap() {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
|
||||
start = now;
|
||||
return (double) duration.count();
|
||||
}
|
||||
|
||||
/// Like \ref lap(), but return a human-readable string
|
||||
std::string lapString(bool precise = false) {
|
||||
return timeString(lap(), precise);
|
||||
}
|
||||
private:
|
||||
std::chrono::system_clock::time_point start;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
98
cs440-acg/include/nori/transform.h
Normal file
98
cs440-acg/include/nori/transform.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/common.h>
|
||||
#include <nori/ray.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* \brief Homogeneous coordinate transformation
|
||||
*
|
||||
* This class stores a general homogeneous coordinate tranformation, such as
|
||||
* rotation, translation, uniform or non-uniform scaling, and perspective
|
||||
* transformations. The inverse of this transformation is also recorded
|
||||
* here, since it is required when transforming normal vectors.
|
||||
*/
|
||||
struct Transform {
|
||||
public:
|
||||
/// Create the identity transform
|
||||
Transform() :
|
||||
m_transform(Eigen::Matrix4f::Identity()),
|
||||
m_inverse(Eigen::Matrix4f::Identity()) { }
|
||||
|
||||
/// Create a new transform instance for the given matrix
|
||||
Transform(const Eigen::Matrix4f &trafo);
|
||||
|
||||
/// Create a new transform instance for the given matrix and its inverse
|
||||
Transform(const Eigen::Matrix4f &trafo, const Eigen::Matrix4f &inv)
|
||||
: m_transform(trafo), m_inverse(inv) { }
|
||||
|
||||
/// Return the underlying matrix
|
||||
const Eigen::Matrix4f &getMatrix() const {
|
||||
return m_transform;
|
||||
}
|
||||
|
||||
/// Return the inverse of the underlying matrix
|
||||
const Eigen::Matrix4f &getInverseMatrix() const {
|
||||
return m_inverse;
|
||||
}
|
||||
|
||||
/// Return the inverse transformation
|
||||
Transform inverse() const {
|
||||
return Transform(m_inverse, m_transform);
|
||||
}
|
||||
|
||||
/// Concatenate with another transform
|
||||
Transform operator*(const Transform &t) const;
|
||||
|
||||
/// Apply the homogeneous transformation to a 3D vector
|
||||
Vector3f operator*(const Vector3f &v) const {
|
||||
return m_transform.topLeftCorner<3,3>() * v;
|
||||
}
|
||||
|
||||
/// Apply the homogeneous transformation to a 3D normal
|
||||
Normal3f operator*(const Normal3f &n) const {
|
||||
return m_inverse.topLeftCorner<3, 3>().transpose() * n;
|
||||
}
|
||||
|
||||
/// Transform a point by an arbitrary matrix in homogeneous coordinates
|
||||
Point3f operator*(const Point3f &p) const {
|
||||
Vector4f result = m_transform * Vector4f(p[0], p[1], p[2], 1.0f);
|
||||
return result.head<3>() / result.w();
|
||||
}
|
||||
|
||||
/// Apply the homogeneous transformation to a ray
|
||||
Ray3f operator*(const Ray3f &r) const {
|
||||
return Ray3f(
|
||||
operator*(r.o),
|
||||
operator*(r.d),
|
||||
r.mint, r.maxt
|
||||
);
|
||||
}
|
||||
|
||||
/// Return a string representation
|
||||
std::string toString() const;
|
||||
private:
|
||||
Eigen::Matrix4f m_transform;
|
||||
Eigen::Matrix4f m_inverse;
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
169
cs440-acg/include/nori/vector.h
Normal file
169
cs440-acg/include/nori/vector.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/common.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/* ===================================================================
|
||||
This file contains a few templates and specializations, which
|
||||
provide 2/3D points, vectors, and normals over different
|
||||
underlying data types. Points, vectors, and normals are distinct
|
||||
in Nori, because they transform differently under homogeneous
|
||||
coordinate transformations.
|
||||
* =================================================================== */
|
||||
|
||||
/**
|
||||
* \brief Generic N-dimensional vector data structure based on Eigen::Matrix
|
||||
*/
|
||||
template <typename _Scalar, int _Dimension> struct TVector : public Eigen::Matrix<_Scalar, _Dimension, 1> {
|
||||
public:
|
||||
enum {
|
||||
Dimension = _Dimension
|
||||
};
|
||||
|
||||
typedef _Scalar Scalar;
|
||||
typedef Eigen::Matrix<Scalar, Dimension, 1> Base;
|
||||
typedef TVector<Scalar, Dimension> VectorType;
|
||||
typedef TPoint<Scalar, Dimension> PointType;
|
||||
|
||||
/// Create a new vector with constant component vlaues
|
||||
TVector(Scalar value = (Scalar) 0) { Base::setConstant(value); }
|
||||
|
||||
/// Create a new 2D vector (type error if \c Dimension != 2)
|
||||
TVector(Scalar x, Scalar y) : Base(x, y) { }
|
||||
|
||||
/// Create a new 3D vector (type error if \c Dimension != 3)
|
||||
TVector(Scalar x, Scalar y, Scalar z) : Base(x, y, z) { }
|
||||
|
||||
/// Create a new 4D vector (type error if \c Dimension != 4)
|
||||
TVector(Scalar x, Scalar y, Scalar z, Scalar w) : Base(x, y, z, w) { }
|
||||
|
||||
/// Construct a vector from MatrixBase (needed to play nice with Eigen)
|
||||
template <typename Derived> TVector(const Eigen::MatrixBase<Derived>& p)
|
||||
: Base(p) { }
|
||||
|
||||
/// Assign a vector from MatrixBase (needed to play nice with Eigen)
|
||||
template <typename Derived> TVector &operator=(const Eigen::MatrixBase<Derived>& p) {
|
||||
this->Base::operator=(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Return a human-readable string summary
|
||||
std::string toString() const {
|
||||
std::string result;
|
||||
for (size_t i=0; i<Dimension; ++i) {
|
||||
result += std::to_string(this->coeff(i));
|
||||
if (i+1 < Dimension)
|
||||
result += ", ";
|
||||
}
|
||||
return "[" + result + "]";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Generic N-dimensional point data structure based on Eigen::Matrix
|
||||
*/
|
||||
template <typename _Scalar, int _Dimension> struct TPoint : public Eigen::Matrix<_Scalar, _Dimension, 1> {
|
||||
public:
|
||||
enum {
|
||||
Dimension = _Dimension
|
||||
};
|
||||
|
||||
typedef _Scalar Scalar;
|
||||
typedef Eigen::Matrix<Scalar, Dimension, 1> Base;
|
||||
typedef TVector<Scalar, Dimension> VectorType;
|
||||
typedef TPoint<Scalar, Dimension> PointType;
|
||||
|
||||
/// Create a new point with constant component vlaues
|
||||
TPoint(Scalar value = (Scalar) 0) { Base::setConstant(value); }
|
||||
|
||||
/// Create a new 2D point (type error if \c Dimension != 2)
|
||||
TPoint(Scalar x, Scalar y) : Base(x, y) { }
|
||||
|
||||
/// Create a new 3D point (type error if \c Dimension != 3)
|
||||
TPoint(Scalar x, Scalar y, Scalar z) : Base(x, y, z) { }
|
||||
|
||||
/// Create a new 4D point (type error if \c Dimension != 4)
|
||||
TPoint(Scalar x, Scalar y, Scalar z, Scalar w) : Base(x, y, z, w) { }
|
||||
|
||||
/// Construct a point from MatrixBase (needed to play nice with Eigen)
|
||||
template <typename Derived> TPoint(const Eigen::MatrixBase<Derived>& p)
|
||||
: Base(p) { }
|
||||
|
||||
/// Assign a point from MatrixBase (needed to play nice with Eigen)
|
||||
template <typename Derived> TPoint &operator=(const Eigen::MatrixBase<Derived>& p) {
|
||||
this->Base::operator=(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Return a human-readable string summary
|
||||
std::string toString() const {
|
||||
std::string result;
|
||||
for (size_t i=0; i<Dimension; ++i) {
|
||||
result += std::to_string(this->coeff(i));
|
||||
if (i+1 < Dimension)
|
||||
result += ", ";
|
||||
}
|
||||
return "[" + result + "]";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief 3-dimensional surface normal representation
|
||||
*/
|
||||
struct Normal3f : public Eigen::Matrix<float, 3, 1> {
|
||||
public:
|
||||
enum {
|
||||
Dimension = 3
|
||||
};
|
||||
|
||||
typedef float Scalar;
|
||||
typedef Eigen::Matrix<Scalar, Dimension, 1> Base;
|
||||
typedef TVector<Scalar, Dimension> VectorType;
|
||||
typedef TPoint<Scalar, Dimension> PointType;
|
||||
|
||||
|
||||
/// Create a new normal with constant component vlaues
|
||||
Normal3f(Scalar value = 0.0f) { Base::setConstant(value); }
|
||||
|
||||
/// Create a new 3D normal
|
||||
Normal3f(Scalar x, Scalar y, Scalar z) : Base(x, y, z) { }
|
||||
|
||||
/// Construct a normal from MatrixBase (needed to play nice with Eigen)
|
||||
template <typename Derived> Normal3f(const Eigen::MatrixBase<Derived>& p)
|
||||
: Base(p) { }
|
||||
|
||||
/// Assign a normal from MatrixBase (needed to play nice with Eigen)
|
||||
template <typename Derived> Normal3f &operator=(const Eigen::MatrixBase<Derived>& p) {
|
||||
this->Base::operator=(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Return a human-readable string summary
|
||||
std::string toString() const {
|
||||
return tfm::format("[%f, %f, %f]", coeff(0), coeff(1), coeff(2));
|
||||
}
|
||||
};
|
||||
|
||||
/// Complete the set {a} to an orthonormal base
|
||||
extern void coordinateSystem(const Vector3f &a, Vector3f &b, Vector3f &c);
|
||||
|
||||
NORI_NAMESPACE_END
|
87
cs440-acg/include/nori/warp.h
Normal file
87
cs440-acg/include/nori/warp.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
This file is part of Nori, a simple educational ray tracer
|
||||
|
||||
Copyright (c) 2015 by Wenzel Jakob
|
||||
|
||||
Nori 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.
|
||||
|
||||
Nori 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
|
||||
|
||||
#include <nori/common.h>
|
||||
#include <nori/mipmap.h>
|
||||
#include <nori/sampler.h>
|
||||
|
||||
NORI_NAMESPACE_BEGIN
|
||||
|
||||
/// A collection of useful warping functions for importance sampling
|
||||
class Warp {
|
||||
public:
|
||||
/// Dummy warping function: takes uniformly distributed points in a square and just returns them
|
||||
static Point2f squareToUniformSquare(const Point2f &sample);
|
||||
|
||||
/// Probability density of \ref squareToUniformSquare()
|
||||
static float squareToUniformSquarePdf(const Point2f &p);
|
||||
|
||||
/// Sample a 2D tent distribution
|
||||
static Point2f squareToTent(const Point2f &sample);
|
||||
|
||||
/// Probability density of \ref squareToTent()
|
||||
static float squareToTentPdf(const Point2f &p);
|
||||
|
||||
/// Uniformly sample a vector on a 2D disk with radius 1, centered around the origin
|
||||
static Point2f squareToUniformDisk(const Point2f &sample);
|
||||
|
||||
/// Probability density of \ref squareToUniformDisk()
|
||||
static float squareToUniformDiskPdf(const Point2f &p);
|
||||
|
||||
/// Uniformly sample a vector on the unit sphere with respect to solid angles
|
||||
static Vector3f squareToUniformSphere(const Point2f &sample);
|
||||
|
||||
/// Probability density of \ref squareToUniformSphere()
|
||||
static float squareToUniformSpherePdf(const Vector3f &v);
|
||||
|
||||
/// Uniformly sample a vector on the unit hemisphere around the pole (0,0,1) with respect to solid angles
|
||||
static Vector3f squareToUniformHemisphere(const Point2f &sample);
|
||||
|
||||
/// Probability density of \ref squareToUniformHemisphere()
|
||||
static float squareToUniformHemispherePdf(const Vector3f &v);
|
||||
|
||||
/// Uniformly sample a vector on the unit hemisphere around the pole (0,0,1) with respect to projected solid angles
|
||||
static Vector3f squareToCosineHemisphere(const Point2f &sample);
|
||||
|
||||
/// Probability density of \ref squareToCosineHemisphere()
|
||||
static float squareToCosineHemispherePdf(const Vector3f &v);
|
||||
|
||||
/// Warp a uniformly distributed square sample to a Beckmann distribution * cosine for the given 'alpha' parameter
|
||||
static Vector3f squareToBeckmann(const Point2f &sample, float alpha);
|
||||
|
||||
/// Probability density of \ref squareToBeckmann()
|
||||
static float squareToBeckmannPdf(const Vector3f &m, float alpha);
|
||||
|
||||
/// Warp a uniformly distributed square sample using Hierarchical Sample Warping
|
||||
static Point2f squareToHSW(const Point2f &sample, const Mipmap &mm);
|
||||
|
||||
/// Probability density of \ref squareToHSW()
|
||||
static float squareToHSWPdf(const Point2f &m, const Mipmap &mm);
|
||||
|
||||
static Vector3f squareToGTR1(const Point2f & sample, float a);
|
||||
|
||||
static float squareToGTR1Pdf(const Vector3f & m, float a);
|
||||
|
||||
static Vector3f squareToGTR2(const Point2f & sample, float a);
|
||||
|
||||
static float squareToGTR2Pdf(const Vector3f & m, float a);
|
||||
};
|
||||
|
||||
NORI_NAMESPACE_END
|
Reference in New Issue
Block a user