Nori  23
perspective.cpp
1 /*
2  This file is part of Nori, a simple educational ray tracer
3 
4  Copyright (c) 2015 by Wenzel Jakob, Romain Prévost
5 
6  Nori is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Nori is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <nori/camera.h>
20 #include <nori/rfilter.h>
21 #include <nori/warp.h>
22 #include <Eigen/Geometry>
23 
24 NORI_NAMESPACE_BEGIN
25 
32 class PerspectiveCamera : public Camera {
33 public:
34  PerspectiveCamera(const PropertyList &propList) {
35  /* Width and height in pixels. Default: 720p */
36  m_outputSize.x() = propList.getInteger("width", 1280);
37  m_outputSize.y() = propList.getInteger("height", 720);
38  m_invOutputSize = m_outputSize.cast<float>().cwiseInverse();
39 
40  /* Specifies an optional camera-to-world transformation. Default: none */
41  m_cameraToWorld = propList.getTransform("toWorld", Transform());
42 
43  /* Horizontal field of view in degrees */
44  m_fov = propList.getFloat("fov", 30.0f);
45 
46  /* Near and far clipping planes in world-space units */
47  m_nearClip = propList.getFloat("nearClip", 1e-4f);
48  m_farClip = propList.getFloat("farClip", 1e4f);
49 
50  m_rfilter = NULL;
51  }
52 
53  virtual void activate() override {
54  float aspect = m_outputSize.x() / (float) m_outputSize.y();
55 
56  /* Project vectors in camera space onto a plane at z=1:
57  *
58  * xProj = cot * x / z
59  * yProj = cot * y / z
60  * zProj = (far * (z - near)) / (z * (far-near))
61  * The cotangent factor ensures that the field of view is
62  * mapped to the interval [-1, 1].
63  */
64  float recip = 1.0f / (m_farClip - m_nearClip),
65  cot = 1.0f / std::tan(degToRad(m_fov / 2.0f));
66 
67  Eigen::Matrix4f perspective;
68  perspective <<
69  cot, 0, 0, 0,
70  0, cot, 0, 0,
71  0, 0, m_farClip * recip, -m_nearClip * m_farClip * recip,
72  0, 0, 1, 0;
73 
78  m_sampleToCamera = Transform(
79  Eigen::DiagonalMatrix<float, 3>(Vector3f(0.5f, -0.5f * aspect, 1.0f)) *
80  Eigen::Translation<float, 3>(1.0f, -1.0f/aspect, 0.0f) * perspective).inverse();
81 
82  /* If no reconstruction filter was assigned, instantiate a Gaussian filter */
83  if (!m_rfilter) {
84  m_rfilter = static_cast<ReconstructionFilter *>(
86  m_rfilter->activate();
87  }
88  }
89 
91  const Point2f &samplePosition,
92  const Point2f &apertureSample) const {
93  /* Compute the corresponding position on the
94  near plane (in local camera space) */
95  Point3f nearP = m_sampleToCamera * Point3f(
96  samplePosition.x() * m_invOutputSize.x(),
97  samplePosition.y() * m_invOutputSize.y(), 0.0f);
98 
99  /* Turn into a normalized ray direction, and
100  adjust the ray interval accordingly */
101  Vector3f d = nearP.normalized();
102  float invZ = 1.0f / d.z();
103 
104  ray.o = m_cameraToWorld * Point3f(0, 0, 0);
105  ray.d = m_cameraToWorld * d;
106  ray.mint = m_nearClip * invZ;
107  ray.maxt = m_farClip * invZ;
108  ray.update();
109 
110  return Color3f(1.0f);
111  }
112 
113  virtual void addChild(NoriObject *obj) override {
114  switch (obj->getClassType()) {
115  case EReconstructionFilter:
116  if (m_rfilter)
117  throw NoriException("Camera: tried to register multiple reconstruction filters!");
118  m_rfilter = static_cast<ReconstructionFilter *>(obj);
119  break;
120 
121  default:
122  throw NoriException("Camera::addChild(<%s>) is not supported!",
123  classTypeName(obj->getClassType()));
124  }
125  }
126 
128  virtual std::string toString() const override {
129  return tfm::format(
130  "PerspectiveCamera[\n"
131  " cameraToWorld = %s,\n"
132  " outputSize = %s,\n"
133  " fov = %f,\n"
134  " clip = [%f, %f],\n"
135  " rfilter = %s\n"
136  "]",
137  indent(m_cameraToWorld.toString(), 18),
138  m_outputSize.toString(),
139  m_fov,
140  m_nearClip,
141  m_farClip,
142  indent(m_rfilter->toString())
143  );
144  }
145 private:
146  Vector2f m_invOutputSize;
147  Transform m_sampleToCamera;
148  Transform m_cameraToWorld;
149  float m_fov;
150  float m_nearClip;
151  float m_farClip;
152 };
153 
154 NORI_REGISTER_CLASS(PerspectiveCamera, "perspective");
155 NORI_NAMESPACE_END
Generic camera interface.
Definition: camera.h:35
Simple exception class, which stores a human-readable error description.
Definition: common.h:148
static NoriObject * createInstance(const std::string &name, const PropertyList &propList)
Construct an instance from the class of the given name.
Definition: object.h:158
Base class of all objects.
Definition: object.h:32
virtual void activate()
Perform some action associated with the object.
Definition: object.h:107
virtual std::string toString() const =0
Return a brief string summary of the instance (for debugging purposes)
static std::string classTypeName(EClassType type)
Turn a class type into a human-readable string.
Definition: object.h:51
virtual EClassType getClassType() const =0
Return the type of object (i.e. Mesh/BSDF/etc.) provided by this instance.
Perspective camera with depth of field.
Definition: perspective.cpp:32
virtual void activate() override
Perform some action associated with the object.
Definition: perspective.cpp:53
Color3f sampleRay(Ray3f &ray, const Point2f &samplePosition, const Point2f &apertureSample) const
Importance sample a ray according to the camera's response function.
Definition: perspective.cpp:90
virtual std::string toString() const override
Return a human-readable summary.
virtual void addChild(NoriObject *obj) override
Add a child object to the current instance.
This is an associative container used to supply the constructors of NoriObject subclasses with parame...
Definition: proplist.h:32
Transform getTransform(const std::string &name) const
Get a transform property, and throw an exception if it does not exist.
float getFloat(const std::string &name) const
Get a float property, and throw an exception if it does not exist.
int getInteger(const std::string &name) const
Get an integer property, and throw an exception if it does not exist.
Generic radially symmetric image reconstruction filter.
Definition: rfilter.h:41
Represents a linear RGB color value.
Definition: color.h:29
VectorType d
Ray direction.
Definition: ray.h:44
Scalar mint
Minimum position on the ray segment.
Definition: ray.h:46
void update()
Update the reciprocal ray directions after changing 'd'.
Definition: ray.h:75
Scalar maxt
Maximum position on the ray segment.
Definition: ray.h:47
PointType o
Ray origin.
Definition: ray.h:43
std::string toString() const
Return a human-readable string summary.
Definition: vector.h:71
Homogeneous coordinate transformation.
Definition: transform.h:35
std::string toString() const
Return a string representation.
Definition: common.cpp:240
Transform inverse() const
Return the inverse transformation.
Definition: transform.h:60