Line data Source code
1 :
2 : /* Copyright (c) 2006-2010, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2012, 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 "projection.h"
21 : #include "pixelViewport.h"
22 :
23 : #include <lunchbox/log.h>
24 :
25 : #ifndef M_PI
26 : # define M_PI 3.14159265358979323846264338327
27 : #endif
28 : #define DEG2RAD( angle ) ((angle) * static_cast<float>(M_PI) / 180.f)
29 :
30 : namespace eq
31 : {
32 : namespace fabric
33 : {
34 :
35 7949 : Wall::Wall()
36 : : bottomLeft( -.8f, -.5f, -1.f )
37 : , bottomRight( .8f, -.5f, -1.f )
38 : , topLeft( -.8f, .5f, -1.f )
39 7949 : , type( TYPE_FIXED )
40 : {
41 7949 : }
42 :
43 6 : Wall::Wall( const Vector3f& bl, const Vector3f& br, const Vector3f& tl )
44 : : bottomLeft( bl )
45 : , bottomRight( br )
46 : , topLeft( tl )
47 6 : , type( TYPE_FIXED )
48 : {
49 6 : }
50 :
51 2 : void Wall::resizeHorizontal( const float ratio )
52 : {
53 2 : if( ratio == 1.f || ratio < 0.f )
54 2 : return;
55 :
56 2 : const Vector3f u_2 = (bottomRight - bottomLeft) * .5f;
57 2 : const Vector3f delta = u_2 * (ratio - 1.f);
58 2 : bottomLeft -= delta;
59 2 : bottomRight += delta;
60 2 : topLeft -= delta;
61 : }
62 :
63 1 : void Wall::resizeVertical( const float ratio )
64 : {
65 1 : if( ratio == 1.f || ratio < 0.f )
66 1 : return;
67 :
68 1 : const Vector3f v_2 = (topLeft - bottomLeft) * .5f;
69 1 : const Vector3f delta = v_2 * (ratio - 1.f);
70 1 : bottomLeft -= delta;
71 1 : bottomRight -= delta;
72 1 : topLeft += delta;
73 : }
74 :
75 0 : void Wall::resizeLeft( const float ratio )
76 : {
77 0 : if( ratio == 1.f || ratio < 0.f )
78 0 : return;
79 :
80 0 : const Vector3f u = bottomRight - bottomLeft;
81 0 : const Vector3f delta = u * (ratio - 1.f);
82 0 : bottomLeft -= delta;
83 0 : topLeft -= delta;
84 : }
85 :
86 0 : void Wall::resizeRight( const float ratio )
87 : {
88 0 : if( ratio == 1.f || ratio < 0.f )
89 0 : return;
90 :
91 0 : const Vector3f u = bottomRight - bottomLeft;
92 0 : const Vector3f delta = u * (ratio - 1.f);
93 0 : bottomRight += delta;
94 : }
95 :
96 0 : void Wall::resizeTop( const float ratio )
97 : {
98 0 : if( ratio == 1.f || ratio < 0.f )
99 0 : return;
100 :
101 0 : const Vector3f v = topLeft - bottomLeft;
102 0 : const Vector3f delta = v * (ratio - 1.f);
103 0 : topLeft += delta;
104 : }
105 :
106 0 : void Wall::resizeBottom( const float ratio )
107 : {
108 0 : if( ratio == 1.f || ratio < 0.f )
109 0 : return;
110 :
111 0 : const Vector3f v = topLeft - bottomLeft;
112 0 : const Vector3f delta = v * (ratio - 1.f);
113 0 : bottomLeft -= delta;
114 0 : bottomRight -= delta;
115 : }
116 :
117 8 : void Wall::resizeHorizontalToAR( const float aspectRatio )
118 : {
119 8 : const Vector3f u_2 = (bottomRight - bottomLeft) * .5f;
120 8 : const Vector3f v_2 = (topLeft - bottomLeft) * .5f;
121 :
122 8 : const float currentAR = u_2.length() / v_2.length();
123 8 : const float ratio = aspectRatio / currentAR;
124 :
125 : // Same as resizeHorizontal, but C&P since we have u_2 already
126 8 : const Vector3f delta = u_2 * (ratio - 1.f);
127 8 : bottomLeft -= delta;
128 8 : bottomRight += delta;
129 8 : topLeft -= delta;
130 8 : }
131 :
132 368 : void Wall::moveFocus( const Vector3f& eye, const float ratio )
133 : {
134 368 : if( ratio == 1.0f )
135 736 : return;
136 :
137 0 : bottomLeft = eye + ( bottomLeft - eye ) * ratio;
138 0 : bottomRight = eye + ( bottomRight - eye ) * ratio;
139 0 : topLeft = eye + ( topLeft - eye ) * ratio;
140 : }
141 :
142 489 : void Wall::apply( const Viewport& viewport )
143 : {
144 489 : const Vector3f u = bottomRight - bottomLeft;
145 489 : const Vector3f v = topLeft - bottomLeft;
146 :
147 489 : bottomLeft = bottomLeft + u * viewport.x + v * viewport.y;
148 489 : bottomRight = bottomLeft + u * viewport.w;
149 489 : topLeft = bottomLeft + v * viewport.h;
150 489 : }
151 :
152 368 : void Wall::scale( const float ratio )
153 : {
154 368 : if( ratio == 1.0f )
155 736 : return;
156 :
157 0 : bottomLeft *= ratio;
158 0 : bottomRight *= ratio;
159 0 : topLeft *= ratio;
160 : }
161 :
162 11 : Wall& Wall::operator = ( const Projection& projection )
163 : {
164 22 : const float width = fabs( projection.distance * 2.0 *
165 22 : tanf(DEG2RAD( .5f * projection.fov[0] )));
166 22 : const float height = fabs( projection.distance * 2.0 *
167 22 : tanf(DEG2RAD( .5f * projection.fov[1] )));
168 :
169 11 : bottomLeft[0] = -width * 0.5f;
170 11 : bottomLeft[1] = -height * 0.5f;
171 11 : bottomLeft[2] = 0;
172 11 : bottomRight[0] = width * 0.5f;
173 11 : bottomRight[1] = -height * 0.5f;
174 11 : bottomRight[2] = 0;
175 11 : topLeft[0] = -width * 0.5f;
176 11 : topLeft[1] = height * 0.5f;
177 11 : topLeft[2] = 0;
178 :
179 11 : const float cosP = cos(DEG2RAD( projection.hpr[1] ));
180 11 : const float sinP = sin(DEG2RAD( projection.hpr[1] ));
181 11 : const float cosH = cos(DEG2RAD( projection.hpr[0] ));
182 11 : const float sinH = sin(DEG2RAD( projection.hpr[0] ));
183 11 : const float cosR = cos(DEG2RAD( projection.hpr[2] ));
184 11 : const float sinR = sin(DEG2RAD( projection.hpr[2] ));
185 :
186 11 : Matrix3f mat ;
187 11 : const float cosPsinH = cosP * sinH;
188 11 : const float sinPsinH = sinP * sinH;
189 :
190 11 : mat.array[0] = cosH * cosR;
191 11 : mat.array[1] = -cosH * sinR;
192 11 : mat.array[2] = -sinH;
193 11 : mat.array[3] = -sinPsinH * cosR + cosP * sinR;
194 11 : mat.array[4] = sinPsinH * sinR + cosP * cosR;
195 11 : mat.array[5] = -sinP * cosH;
196 11 : mat.array[6] = cosPsinH * cosR + sinP * sinR;
197 11 : mat.array[7] = -cosPsinH * sinR + sinP * cosR;
198 11 : mat.array[8] = cosP * cosH;
199 :
200 11 : bottomLeft = mat * bottomLeft;
201 11 : bottomRight = mat * bottomRight;
202 11 : topLeft = mat * topLeft;
203 :
204 11 : Vector3f w( mat.array[6], mat.array[7], mat.array[8] );
205 :
206 11 : bottomLeft = bottomLeft + projection.origin + w * projection.distance;
207 11 : bottomRight = bottomRight + projection.origin + w * projection.distance;
208 11 : topLeft = topLeft + projection.origin + w * projection.distance;
209 :
210 11 : return *this;
211 : }
212 :
213 1 : Wall& Wall::operator = ( const Matrix4f& xfm )
214 : {
215 1 : bottomLeft = xfm * Vector4f( -1.0f, -1.0f, -1.0f, 1.0f );
216 1 : bottomRight = xfm * Vector4f( 1.0f, -1.0f, -1.0f, 1.0f );
217 1 : topLeft = xfm * Vector4f( -1.0f, 1.0f, -1.0f, 1.0f );
218 1 : return *this;
219 : }
220 :
221 1755 : bool Wall::operator == ( const Wall& rhs ) const
222 : {
223 2777 : return ( bottomLeft.equals( rhs.bottomLeft, 0.0001f ) &&
224 2769 : bottomRight.equals( rhs.bottomRight, 0.0001f ) &&
225 2769 : topLeft.equals( rhs.topLeft, 0.0001f ));
226 : }
227 :
228 0 : bool Wall::operator != ( const Wall& rhs ) const
229 : {
230 0 : return ( !bottomLeft.equals( rhs.bottomLeft, 0.0001f ) ||
231 0 : !bottomRight.equals( rhs.bottomRight, 0.0001f ) ||
232 0 : !topLeft.equals( rhs.topLeft, 0.0001f ));
233 : }
234 :
235 399 : std::ostream& operator << ( std::ostream& os, const Wall& wall )
236 : {
237 399 : const std::ios::fmtflags flags = os.flags();
238 399 : os.setf( std::ios::fixed, std::ios::floatfield );
239 :
240 399 : os << lunchbox::disableHeader << lunchbox::disableFlush
241 399 : << "wall" << std::endl
242 399 : << "{" << std::endl << lunchbox::indent
243 798 : << "bottom_left " << wall.bottomLeft << std::endl
244 798 : << "bottom_right " << wall.bottomRight << std::endl
245 798 : << "top_left " << wall.topLeft << std::endl;
246 399 : if( wall.type != Wall::TYPE_FIXED )
247 6 : os << "type " << wall.type << std::endl;
248 399 : os << lunchbox::exdent << "}"
249 399 : << lunchbox::enableFlush << lunchbox::enableHeader << std::endl;
250 :
251 399 : os.setf( flags );
252 399 : return os;
253 : }
254 :
255 6 : std::ostream& operator << ( std::ostream& os, const Wall::Type& type )
256 : {
257 6 : switch( type )
258 : {
259 : case Wall::TYPE_HMD:
260 6 : os << "HMD";
261 6 : break;
262 :
263 : default:
264 0 : LBASSERT( false );
265 :
266 : case Wall::TYPE_FIXED:
267 0 : os << "fixed";
268 0 : break;
269 : }
270 6 : return os;
271 : }
272 :
273 : }
274 45 : }
|