Line data Source code
1 :
2 : /* Copyright (c) 2007-2016, Stefan Eilemann <eile@equalizergraphics.com>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 : #include "projection.h"
19 : #include "vmmlib.h"
20 : #include "wall.h"
21 :
22 : #include <lunchbox/log.h>
23 :
24 : #define DEG2RAD(angle) ((angle) * static_cast<float>(M_PI) / 180.f)
25 : #define RAD2DEG(angle) ((angle)*180.f / static_cast<float>(M_PI))
26 :
27 : namespace eq
28 : {
29 : namespace fabric
30 : {
31 12436 : Projection::Projection()
32 : : origin(0.f, 0.f, 0.f)
33 : , distance(1.f)
34 : , fov(77.3196f, 53.1301f)
35 12436 : , hpr(0.f, 0.f, 0.f)
36 : {
37 12436 : }
38 :
39 0 : void Projection::resizeHorizontal(const float ratio)
40 : {
41 0 : if (ratio == 1.f || ratio < 0.f)
42 0 : return;
43 :
44 : // const float newWidth_2 = ratio * distance * tanf(DEG2RAD( .5f * fov[1]
45 : // ));
46 : // fov[1] = 2.f * atanf( newWidth_2 / distance );
47 : // -> distance can be removed:
48 0 : fov[0] = RAD2DEG(2.f * atanf(ratio * tanf(DEG2RAD(.5f * fov[0]))));
49 : }
50 :
51 0 : void Projection::resizeVertical(const float ratio)
52 : {
53 0 : if (ratio == 1.f || ratio < 0.f)
54 0 : return;
55 :
56 : // see resizeHorizontal
57 0 : fov[1] = RAD2DEG(2.f * atanf(ratio * tanf(DEG2RAD(.5f * fov[1]))));
58 : }
59 :
60 1326 : Projection& Projection::operator=(const Wall& wall)
61 : {
62 1326 : Vector3f u = wall.bottomRight - wall.bottomLeft;
63 1326 : Vector3f v = wall.topLeft - wall.bottomLeft;
64 1326 : const float width = u.normalize();
65 1326 : const float height = v.normalize();
66 :
67 1326 : const Vector3f w = vmml::cross(u, v);
68 2652 : const Vector3f center((wall.bottomRight[0] + wall.topLeft[0]) * 0.5f,
69 2652 : (wall.bottomRight[1] + wall.topLeft[1]) * 0.5f,
70 3978 : (wall.bottomRight[2] + wall.topLeft[2]) * 0.5f);
71 :
72 1326 : if (distance <= std::numeric_limits<float>::epsilon())
73 0 : distance = center.length();
74 :
75 1326 : Matrix3f mat;
76 1326 : mat.array[0] = u[0];
77 1326 : mat.array[1] = u[1];
78 1326 : mat.array[2] = u[2];
79 :
80 1326 : mat.array[3] = v[0];
81 1326 : mat.array[4] = v[1];
82 1326 : mat.array[5] = v[2];
83 :
84 1326 : mat.array[6] = w[0];
85 1326 : mat.array[7] = w[1];
86 1326 : mat.array[8] = w[2];
87 :
88 1326 : fov[0] = RAD2DEG(atanf(0.5f * width / distance)) * 2.0f;
89 1326 : fov[1] = RAD2DEG(atanf(0.5f * height / distance)) * 2.0f;
90 :
91 1326 : hpr[0] = -asinf(mat.array[2]);
92 1326 : const float cosH = cosf(hpr[0]);
93 1326 : hpr[0] = RAD2DEG(hpr[0]);
94 :
95 1326 : if (fabs(cosH) > std::numeric_limits<float>::epsilon())
96 : {
97 1292 : float tr_x = mat.array[8] / cosH;
98 1292 : float tr_y = -mat.array[5] / cosH;
99 1292 : hpr[1] = RAD2DEG(atan2f(tr_y, tr_x));
100 :
101 1292 : tr_x = mat.array[0] / cosH;
102 1292 : tr_y = -mat.array[1] / cosH;
103 1292 : hpr[2] = RAD2DEG(atan2f(tr_y, tr_x));
104 : }
105 : else
106 : {
107 34 : hpr[1] = 0.f;
108 :
109 34 : const float tr_x = mat.array[4];
110 34 : const float tr_y = mat.array[3];
111 :
112 34 : hpr[2] = RAD2DEG(atan2f(tr_y, tr_x));
113 : }
114 :
115 1326 : origin = center - w * distance;
116 1326 : return *this;
117 : }
118 :
119 142 : bool Projection::operator==(const Projection& rhs) const
120 : {
121 148 : return (origin.equals(rhs.origin, 0.0001f) &&
122 12 : (fabsf(distance - rhs.distance) < 0.0001f) &&
123 154 : fov.equals(rhs.fov, 0.0001f) && hpr.equals(rhs.hpr, 0.0001f));
124 : }
125 :
126 0 : bool Projection::operator!=(const Projection& rhs) const
127 : {
128 0 : return (!origin.equals(rhs.origin, 0.0001f) ||
129 0 : (fabsf(distance - rhs.distance) >= 0.0001f) ||
130 0 : !fov.equals(rhs.fov, 0.0001f) || !hpr.equals(rhs.hpr, 0.0001f));
131 : }
132 :
133 34 : std::ostream& operator<<(std::ostream& os, const Projection& projection)
134 : {
135 34 : const std::ios::fmtflags flags = os.flags();
136 34 : os.setf(std::ios::fixed, std::ios::floatfield);
137 :
138 34 : os << "projection" << std::endl
139 34 : << "{" << std::endl
140 68 : << lunchbox::indent << "origin " << projection.origin << std::endl
141 68 : << "distance " << projection.distance << std::endl
142 68 : << "fov " << projection.fov << std::endl
143 68 : << "hpr " << projection.hpr << std::endl
144 34 : << lunchbox::exdent << "}";
145 :
146 34 : os.setf(flags);
147 34 : return os;
148 : }
149 : }
150 60 : }
|