Line data Source code
1 :
2 : /* Copyright (c) 2006-2016, Stefan Eilemann <eile@equalizergraphics.com>
3 : * Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #include "wall.h"
20 : #include "pixelViewport.h"
21 : #include "projection.h"
22 : #include "vmmlib.h"
23 :
24 : #include <lunchbox/log.h>
25 :
26 : #define DEG2RAD(angle) ((angle) * static_cast<float>(M_PI) / 180.f)
27 :
28 : namespace eq
29 : {
30 : namespace fabric
31 : {
32 13730 : Wall::Wall()
33 : : bottomLeft(-.8f, -.5f, -1.f)
34 : , bottomRight(.8f, -.5f, -1.f)
35 : , topLeft(-.8f, .5f, -1.f)
36 13730 : , type(TYPE_FIXED)
37 : {
38 13730 : }
39 :
40 12 : Wall::Wall(const Vector3f& bl, const Vector3f& br, const Vector3f& tl)
41 : : bottomLeft(bl)
42 : , bottomRight(br)
43 : , topLeft(tl)
44 12 : , type(TYPE_FIXED)
45 : {
46 12 : }
47 :
48 4 : void Wall::resizeHorizontal(const float ratio)
49 : {
50 4 : if (ratio == 1.f || ratio < 0.f)
51 0 : return;
52 :
53 4 : const Vector3f u_2 = (bottomRight - bottomLeft) * .5f;
54 4 : const Vector3f delta = u_2 * (ratio - 1.f);
55 4 : bottomLeft -= delta;
56 4 : bottomRight += delta;
57 4 : topLeft -= delta;
58 : }
59 :
60 2 : void Wall::resizeVertical(const float ratio)
61 : {
62 2 : if (ratio == 1.f || ratio < 0.f)
63 0 : return;
64 :
65 2 : const Vector3f v_2 = (topLeft - bottomLeft) * .5f;
66 2 : const Vector3f delta = v_2 * (ratio - 1.f);
67 2 : bottomLeft -= delta;
68 2 : bottomRight -= delta;
69 2 : topLeft += delta;
70 : }
71 :
72 0 : void Wall::resizeLeft(const float ratio)
73 : {
74 0 : if (ratio == 1.f || ratio < 0.f)
75 0 : return;
76 :
77 0 : const Vector3f u = bottomRight - bottomLeft;
78 0 : const Vector3f delta = u * (ratio - 1.f);
79 0 : bottomLeft -= delta;
80 0 : topLeft -= delta;
81 : }
82 :
83 0 : void Wall::resizeRight(const float ratio)
84 : {
85 0 : if (ratio == 1.f || ratio < 0.f)
86 0 : return;
87 :
88 0 : const Vector3f u = bottomRight - bottomLeft;
89 0 : const Vector3f delta = u * (ratio - 1.f);
90 0 : bottomRight += delta;
91 : }
92 :
93 0 : void Wall::resizeTop(const float ratio)
94 : {
95 0 : if (ratio == 1.f || ratio < 0.f)
96 0 : return;
97 :
98 0 : const Vector3f v = topLeft - bottomLeft;
99 0 : const Vector3f delta = v * (ratio - 1.f);
100 0 : topLeft += delta;
101 : }
102 :
103 0 : void Wall::resizeBottom(const float ratio)
104 : {
105 0 : if (ratio == 1.f || ratio < 0.f)
106 0 : return;
107 :
108 0 : const Vector3f v = topLeft - bottomLeft;
109 0 : const Vector3f delta = v * (ratio - 1.f);
110 0 : bottomLeft -= delta;
111 0 : bottomRight -= delta;
112 : }
113 :
114 2 : void Wall::resizeHorizontalToAR(const float aspectRatio)
115 : {
116 2 : const Vector3f u_2 = (bottomRight - bottomLeft) * .5f;
117 2 : const Vector3f v_2 = (topLeft - bottomLeft) * .5f;
118 :
119 2 : const float currentAR = u_2.length() / v_2.length();
120 2 : const float ratio = aspectRatio / currentAR;
121 :
122 : // Same as resizeHorizontal, but C&P since we have u_2 already
123 2 : const Vector3f delta = u_2 * (ratio - 1.f);
124 2 : bottomLeft -= delta;
125 2 : bottomRight += delta;
126 2 : topLeft -= delta;
127 2 : }
128 :
129 118 : void Wall::moveFocus(const Vector3f& eye, const float ratio)
130 : {
131 118 : if (ratio == 1.0f)
132 118 : return;
133 :
134 0 : bottomLeft = eye + (bottomLeft - eye) * ratio;
135 0 : bottomRight = eye + (bottomRight - eye) * ratio;
136 0 : topLeft = eye + (topLeft - eye) * ratio;
137 : }
138 :
139 422 : void Wall::apply(const Viewport& viewport)
140 : {
141 422 : const Vector3f u = bottomRight - bottomLeft;
142 422 : const Vector3f v = topLeft - bottomLeft;
143 :
144 422 : bottomLeft = bottomLeft + u * viewport.x + v * viewport.y;
145 422 : bottomRight = bottomLeft + u * viewport.w;
146 422 : topLeft = bottomLeft + v * viewport.h;
147 422 : }
148 :
149 118 : void Wall::scale(const float ratio)
150 : {
151 118 : if (ratio == 1.0f)
152 118 : return;
153 :
154 0 : bottomLeft *= ratio;
155 0 : bottomRight *= ratio;
156 0 : topLeft *= ratio;
157 : }
158 :
159 78 : Wall& Wall::operator=(const Projection& projection)
160 : {
161 156 : const float width = fabs(projection.distance * 2.0 *
162 156 : tanf(DEG2RAD(.5f * projection.fov[0])));
163 156 : const float height = fabs(projection.distance * 2.0 *
164 156 : tanf(DEG2RAD(.5f * projection.fov[1])));
165 :
166 78 : bottomLeft[0] = -width * 0.5f;
167 78 : bottomLeft[1] = -height * 0.5f;
168 78 : bottomLeft[2] = 0;
169 78 : bottomRight[0] = width * 0.5f;
170 78 : bottomRight[1] = -height * 0.5f;
171 78 : bottomRight[2] = 0;
172 78 : topLeft[0] = -width * 0.5f;
173 78 : topLeft[1] = height * 0.5f;
174 78 : topLeft[2] = 0;
175 :
176 78 : const float cosP = cos(DEG2RAD(projection.hpr[1]));
177 78 : const float sinP = sin(DEG2RAD(projection.hpr[1]));
178 78 : const float cosH = cos(DEG2RAD(projection.hpr[0]));
179 78 : const float sinH = sin(DEG2RAD(projection.hpr[0]));
180 78 : const float cosR = cos(DEG2RAD(projection.hpr[2]));
181 78 : const float sinR = sin(DEG2RAD(projection.hpr[2]));
182 :
183 78 : Matrix3f mat;
184 78 : const float cosPsinH = cosP * sinH;
185 78 : const float sinPsinH = sinP * sinH;
186 :
187 78 : mat.array[0] = cosH * cosR;
188 78 : mat.array[1] = -cosH * sinR;
189 78 : mat.array[2] = -sinH;
190 78 : mat.array[3] = -sinPsinH * cosR + cosP * sinR;
191 78 : mat.array[4] = sinPsinH * sinR + cosP * cosR;
192 78 : mat.array[5] = -sinP * cosH;
193 78 : mat.array[6] = cosPsinH * cosR + sinP * sinR;
194 78 : mat.array[7] = -cosPsinH * sinR + sinP * cosR;
195 78 : mat.array[8] = cosP * cosH;
196 :
197 78 : bottomLeft = mat * bottomLeft;
198 78 : bottomRight = mat * bottomRight;
199 78 : topLeft = mat * topLeft;
200 :
201 78 : Vector3f w(mat.array[6], mat.array[7], mat.array[8]);
202 :
203 78 : bottomLeft = bottomLeft + projection.origin + w * projection.distance;
204 78 : bottomRight = bottomRight + projection.origin + w * projection.distance;
205 78 : topLeft = topLeft + projection.origin + w * projection.distance;
206 :
207 78 : return *this;
208 : }
209 :
210 2 : Wall& Wall::operator=(const Matrix4f& xfm)
211 : {
212 2 : bottomLeft = xfm * Vector4f(-1.0f, -1.0f, -1.0f, 1.0f);
213 2 : bottomRight = xfm * Vector4f(1.0f, -1.0f, -1.0f, 1.0f);
214 2 : topLeft = xfm * Vector4f(-1.0f, 1.0f, -1.0f, 1.0f);
215 2 : return *this;
216 : }
217 :
218 2808 : bool Wall::operator==(const Wall& rhs) const
219 : {
220 4240 : return (bottomLeft.equals(rhs.bottomLeft, 0.0001f) &&
221 4208 : bottomRight.equals(rhs.bottomRight, 0.0001f) &&
222 4208 : topLeft.equals(rhs.topLeft, 0.0001f));
223 : }
224 :
225 0 : bool Wall::operator!=(const Wall& rhs) const
226 : {
227 0 : return (!bottomLeft.equals(rhs.bottomLeft, 0.0001f) ||
228 0 : !bottomRight.equals(rhs.bottomRight, 0.0001f) ||
229 0 : !topLeft.equals(rhs.topLeft, 0.0001f));
230 : }
231 :
232 556 : std::ostream& operator<<(std::ostream& os, const Wall& wall)
233 : {
234 556 : const std::ios::fmtflags flags = os.flags();
235 556 : os.setf(std::ios::fixed, std::ios::floatfield);
236 :
237 556 : os << lunchbox::disableHeader << lunchbox::disableFlush << "wall"
238 556 : << std::endl
239 556 : << "{" << std::endl
240 1112 : << lunchbox::indent << "bottom_left " << wall.bottomLeft << std::endl
241 1112 : << "bottom_right " << wall.bottomRight << std::endl
242 1112 : << "top_left " << wall.topLeft << std::endl;
243 556 : if (wall.type != Wall::TYPE_FIXED)
244 12 : os << "type " << wall.type << std::endl;
245 556 : os << lunchbox::exdent << "}" << lunchbox::enableFlush
246 556 : << lunchbox::enableHeader << std::endl;
247 :
248 556 : os.setf(flags);
249 556 : return os;
250 : }
251 :
252 12 : std::ostream& operator<<(std::ostream& os, const Wall::Type& type)
253 : {
254 12 : switch (type)
255 : {
256 : case Wall::TYPE_HMD:
257 12 : os << "HMD";
258 12 : break;
259 :
260 : default:
261 0 : LBASSERT(false);
262 :
263 : case Wall::TYPE_FIXED:
264 0 : os << "fixed";
265 0 : break;
266 : }
267 12 : return os;
268 : }
269 : }
270 60 : }
|