1 /******************************************************************************
2 
3   This source file is part of the Avogadro project.
4 
5   Copyright 2012-2014 Kitware, Inc.
6 
7   This source code is released under the New BSD License, (the "License").
8 
9   Unless required by applicable law or agreed to in writing, software
10   distributed under the License is distributed on an "AS IS" BASIS,
11   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   See the License for the specific language governing permissions and
13   limitations under the License.
14 
15 ******************************************************************************/
16 
17 #ifndef AVOGADRO_RENDERING_CAMERA_H
18 #define AVOGADRO_RENDERING_CAMERA_H
19 
20 #include "avogadrorenderingexport.h"
21 
22 #include <avogadro/core/vector.h> // For vector types.
23 
24 #include <Eigen/Geometry> // For member variables.
25 #include <memory>
26 
27 namespace Avogadro {
28 namespace Rendering {
29 
30 enum Projection
31 {
32   Perspective,
33   Orthographic
34 };
35 
36 // Separate Eigen datastructures to ensure sufficient memory alignment.
37 struct EigenData
38 {
39   EIGEN_MAKE_ALIGNED_OPERATOR_NEW
40   Eigen::Affine3f projection;
41   Eigen::Affine3f modelView;
42 };
43 
44 /**
45  * @class Camera camera.h <avogadro/rendering/camera.h>
46  * @brief The Camera class provides utility functionality useful in camera's
47  * used with 3D scenes.
48  * @author Marcus D. Hanwell
49  */
50 
51 class AVOGADRORENDERING_EXPORT Camera
52 {
53 public:
54   Camera();
55   Camera(const Camera& o);
56   Camera& operator=(const Camera& o);
57   ~Camera();
58 
59   /**
60    * Translate the camera's model view matrix using the supplied translation
61    * vector @p translate.
62    */
63   void translate(const Vector3f& translate);
64 
65   /**
66    * Pretranslate the camera's model view matrix using the supplied translation
67    * vector @p translate.
68    */
69   void preTranslate(const Vector3f& translate);
70 
71   /**
72    * Rotate the camera about the supplied @p axis by @p angle (degrees).
73    */
74   void rotate(float angle, const Vector3f& axis);
75 
76   /**
77    * Prerotate the camera about the supplied @p axis by @p angle (degrees).
78    */
79   void preRotate(float angle, const Vector3f& axis);
80 
81   /**
82    * Modify the matrix, to give the effect of zooming in or out.
83    */
84   void scale(float scale);
85 
86   /**
87    * Set the model-view matrix to the "look at" transformation matrix.
88    * @param eye the position of the eye/camera.
89    * @param center the position to look at.
90    * @param up the vector pointing up.
91    */
92   void lookAt(const Vector3f& eye, const Vector3f& center, const Vector3f& up);
93 
94   /**
95    * Distance to supplied point @p point and the camera.
96    */
97   float distance(const Vector3f& point) const;
98 
99   /**
100    * Projects a point from the scene to the window.
101    */
102   Vector3f project(const Vector3f& point) const;
103 
104   /**
105    * Unprojects a point from the window to the scene.
106    */
107   Vector3f unProject(const Vector3f& point) const;
108 
109   /**
110    * Unprojects a point from the window to the scene, using the supplied
111    * reference point (defaults to the origin if nothing is supplied).
112    */
113   Vector3f unProject(const Vector2f& point,
114                      const Vector3f& reference = Vector3f::Zero()) const;
115 
116   /**
117    * Calculate the perspective projection matrix.
118    * @param fieldOfView angle in degrees in the y direction.
119    * @param aspectRatio is the ratio of width to height.
120    * @param zNear is the distance from the viewer to the near clipping plane.
121    * @param zFar is the distance from the viewer to the far clipping plane.
122    */
123   void calculatePerspective(float fieldOfView, float aspectRatio, float zNear,
124                             float zFar);
125 
126   /**
127    * Calculate the perspective projection matrix. Computes the aspect ratio
128    * from the width and height stored by the Camera object.
129    * @param fieldOfView angle in degrees in the y direction.
130    * @param zNear is the distance from the viewer to the near clipping plane.
131    * @param zFar is the distance from the viewer to the far clipping plane.
132    */
133   void calculatePerspective(float fieldOfView, float zNear, float zFar);
134 
135   /**
136    * Calculate the orthographic projection matrix.
137    * @param left left vertical clipping plane.
138    * @param right right vertical clipping plane.
139    * @param bottom bottom horizontal clipping plane.
140    * @param top top horizontal clipping plane.
141    * @param zNear distance to the near clipping plane.
142    * @param zFar distance to the far clipping plane.
143    */
144   void calculateOrthographic(float left, float right, float bottom, float top,
145                              float zNear, float zFar);
146 
147   /**
148    * Set the dimensions of the viewport in pixels.
149    */
150   void setViewport(int w, int h);
151 
152   /**
153    * Get the width of the viewport in pixels.
154    */
width()155   int width() const { return m_width; }
156 
157   /**
158    * Get the height of the viewport in pixels.
159    */
height()160   int height() const { return m_height; }
161 
162   /**
163    * Set the model view matrix to the identity. This resets the model view
164    * matrix.
165    */
setIdentity()166   void setIdentity() { m_data->modelView.setIdentity(); }
167 
168   /**
169    * Set the projection transform.
170    */
171   void setProjection(const Eigen::Affine3f& transform);
172 
173   /**
174    * Get a reference to the projection matrix.
175    */
176   const Eigen::Affine3f& projection() const;
177 
178   /**
179    * Set the model view transform.
180    */
181   void setModelView(const Eigen::Affine3f& transform);
182 
183   /** Get a reference to the model view matrix. */
184   const Eigen::Affine3f& modelView() const;
185 
186   /**
187    * Set the projection type for this camera (Perspective or Orthographic).
188    * @param proj The projection type to use.
189    */
setProjectionType(Projection proj)190   void setProjectionType(Projection proj) { m_projectionType = proj; }
191 
192   /**
193    * Get the projection type the camera is using.
194    * @return The current projection type.
195    */
projectionType()196   Projection projectionType() const { return m_projectionType; }
197 
198   /**
199    * Set the orthographic scale, this defaults to 1.0. Affects calculation of
200    * the orthographic projection matrix.
201    * @param newScale The factor to scale orthographic projection by.
202    */
setOrthographicScale(float newScale)203   void setOrthographicScale(float newScale) { m_orthographicScale = newScale; }
204 
205   /**
206    * Get the value of the orthographic scale, defaults to 1.0.
207    * @return The current value of the orthographic scale.
208    */
orthographicScale()209   float orthographicScale() const { return m_orthographicScale; }
210 
211 private:
212   int m_width;
213   int m_height;
214   Projection m_projectionType;
215   float m_orthographicScale;
216   std::unique_ptr<EigenData> m_data;
217 };
218 
projection()219 inline const Eigen::Affine3f& Camera::projection() const
220 {
221   return m_data->projection;
222 }
223 
modelView()224 inline const Eigen::Affine3f& Camera::modelView() const
225 {
226   return m_data->modelView;
227 }
228 
229 } // namespace Rendering
230 } // namespace Avogadro
231 
232 #endif // AVOGADRO_RENDERING_CAMERA_H
233