vsg  1.1.0
VulkanSceneGraph library
ProjectionMatrix.h
1 #pragma once
2 
3 /* <editor-fold desc="MIT License">
4 
5 Copyright(c) 2018 Robert Osfield
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 
9 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 
13 </editor-fold> */
14 
15 #include <vsg/app/EllipsoidModel.h>
16 #include <vsg/app/ViewMatrix.h>
17 #include <vsg/io/Logger.h>
18 
19 namespace vsg
20 {
21 
23  class VSG_DECLSPEC ProjectionMatrix : public Inherit<Object, ProjectionMatrix>
24  {
25  public:
26  virtual dmat4 transform() const = 0;
27 
28  virtual dmat4 inverse() const
29  {
30  return vsg::inverse(transform());
31  }
32 
33  virtual void changeExtent(const VkExtent2D& /*prevExtent*/, const VkExtent2D& /*newExtent*/)
34  {
35  }
36  };
37  VSG_type_name(vsg::ProjectionMatrix);
38 
40  class VSG_DECLSPEC Perspective : public Inherit<ProjectionMatrix, Perspective>
41  {
42  public:
43  Perspective() :
44  fieldOfViewY(60.0),
45  aspectRatio(1.0),
46  nearDistance(1.0),
47  farDistance(10000.0)
48  {
49  }
50 
51  Perspective(double fov, double ar, double nd, double fd) :
52  fieldOfViewY(fov),
53  aspectRatio(ar),
54  nearDistance(nd),
55  farDistance(fd)
56  {
57  }
58 
59  dmat4 transform() const override { return perspective(radians(fieldOfViewY), aspectRatio, nearDistance, farDistance); }
60 
61  void changeExtent(const VkExtent2D&, const VkExtent2D& newExtent) override
62  {
63  aspectRatio = static_cast<double>(newExtent.width) / static_cast<double>(newExtent.height);
64  }
65 
66  void read(Input& input) override;
67  void write(Output& output) const override;
68 
69  double fieldOfViewY;
70  double aspectRatio;
71  double nearDistance;
72  double farDistance;
73  };
74  VSG_type_name(vsg::Perspective);
75 
77  class Orthographic : public Inherit<ProjectionMatrix, Orthographic>
78  {
79  public:
80  Orthographic() :
81  left(-1.0),
82  right(1.0),
83  bottom(-1.0),
84  top(1.0),
85  nearDistance(1.0),
86  farDistance(10000.0)
87  {
88  }
89 
90  Orthographic(double l, double r, double b, double t, double nd, double fd) :
91  left(l),
92  right(r),
93  bottom(b),
94  top(t),
95  nearDistance(nd),
96  farDistance(fd)
97  {
98  }
99 
100  dmat4 transform() const override { return orthographic(left, right, bottom, top, nearDistance, farDistance); }
101 
102  void changeExtent(const VkExtent2D& prevExtent, const VkExtent2D& newExtent) override
103  {
104  double oldRatio = static_cast<double>(prevExtent.width) / static_cast<double>(prevExtent.height);
105  double newRatio = static_cast<double>(newExtent.width) / static_cast<double>(newExtent.height);
106  left *= newRatio / oldRatio;
107  right *= newRatio / oldRatio;
108  }
109 
110  double left;
111  double right;
112  double bottom;
113  double top;
114  double nearDistance;
115  double farDistance;
116  };
117  VSG_type_name(vsg::Orthographic);
118 
120  class RelativeProjection : public Inherit<ProjectionMatrix, RelativeProjection>
121  {
122  public:
124  projectionMatrix(pm),
125  matrix(m)
126  {
127  }
128 
130  dmat4 transform() const override
131  {
132  return matrix * projectionMatrix->transform();
133  }
134 
135  void changeExtent(const VkExtent2D& prevExtent, const VkExtent2D& newExtent) override
136  {
137  double oldRatio = static_cast<double>(prevExtent.width) / static_cast<double>(prevExtent.height);
138  double newRatio = static_cast<double>(newExtent.width) / static_cast<double>(newExtent.height);
139  matrix = scale(oldRatio / newRatio, 1.0, 1.0) * matrix;
140  }
141  ref_ptr<ProjectionMatrix> projectionMatrix;
142  dmat4 matrix;
143  };
144  VSG_type_name(vsg::RelativeProjection);
145 
148  class EllipsoidPerspective : public Inherit<ProjectionMatrix, EllipsoidPerspective>
149  {
150  public:
152  lookAt(la),
153  ellipsoidModel(em),
154  fieldOfViewY(60.0),
155  aspectRatio(1.0),
156  nearFarRatio(0.0001),
157  horizonMountainHeight(1000.0)
158  {
159  }
160 
161  EllipsoidPerspective(ref_ptr<LookAt> la, ref_ptr<EllipsoidModel> em, double fov, double ar, double nfr, double hmh) :
162  lookAt(la),
163  ellipsoidModel(em),
164  fieldOfViewY(fov),
165  aspectRatio(ar),
166  nearFarRatio(nfr),
167  horizonMountainHeight(hmh)
168  {
169  }
170 
171  dmat4 transform() const override
172  {
173  //debug("camera eye : ", lookAt->eye, ", ", ellipsoidModel->convertECEFToLatLongAltitude(lookAt->eye));
174  vsg::dvec3 v = lookAt->eye;
175  vsg::dvec3 lv = vsg::normalize(lookAt->center - lookAt->eye);
176  double R = ellipsoidModel->radiusEquator();
177  double H = ellipsoidModel->convertECEFToLatLongAltitude(v).z;
178  double D = R + H;
179 
180  double alpha = (D > R) ? std::acos(R / D) : 0.0;
181 
182  double beta_ratio = R / (R + horizonMountainHeight);
183  double beta = beta_ratio < 1.0 ? std::acos(beta_ratio) : 0.0;
184 
185  double theta_ratio = -vsg::dot(lv, v) / (vsg::length(lv) * vsg::length(v));
186  double theta = theta_ratio < 1.0 ? std::acos(theta_ratio) : 0.0;
187 
188  double l = R * (std::tan(alpha) + std::tan(beta));
189 
190  double farDistance = std::cos(theta + alpha - vsg::PI * 0.5) * l;
191  double nearDistance = farDistance * nearFarRatio;
192  //debug("H = ", H, ", l = ", l, ", theta = ", vsg::degrees(theta), ", fd = ", farDistance);
193 
194  return perspective(radians(fieldOfViewY), aspectRatio, nearDistance, farDistance);
195  }
196 
197  void changeExtent(const VkExtent2D& prevExtent, const VkExtent2D& newExtent) override
198  {
199  double oldRatio = static_cast<double>(prevExtent.width) / static_cast<double>(prevExtent.height);
200  double newRatio = static_cast<double>(newExtent.width) / static_cast<double>(newExtent.height);
201 
202  aspectRatio *= (newRatio / oldRatio);
203  }
204 
205  ref_ptr<LookAt> lookAt;
206  ref_ptr<EllipsoidModel> ellipsoidModel;
207 
208  double fieldOfViewY;
209  double aspectRatio;
210  double nearFarRatio;
211  double horizonMountainHeight;
212  };
213  VSG_type_name(vsg::EllipsoidPerspective);
214 
215 } // namespace vsg
Definition: ProjectionMatrix.h:149
Definition: Inherit.h:28
Definition: Input.h:44
Orthographic is a ProjectionMatrix that implements the glOrtho model for setting the projection matri...
Definition: ProjectionMatrix.h:78
Definition: Output.h:41
Perspective is a ProjectionMatrix that implements the gluPerspective model for setting the projection...
Definition: ProjectionMatrix.h:41
ProjectionMatrix is a base class for specifying the Camera projection matrix and its inverse.
Definition: ProjectionMatrix.h:24
RelativeProjection is a ProjectionMatrix that decorates another ProjectionMatrix and pre-multiplies i...
Definition: ProjectionMatrix.h:121
dmat4 transform() const override
returns matrix * projectionMatrix->transform()
Definition: ProjectionMatrix.h:130
Definition: ref_ptr.h:22