Line data Source code
1 :
2 : /* Copyright (c) 2007-2011, 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 "wall.h"
20 :
21 : #include <lunchbox/log.h>
22 :
23 : #ifndef M_PI
24 : # define M_PI 3.14159265358979323846264338327
25 : #endif
26 : #define DEG2RAD( angle ) ((angle) * static_cast<float>(M_PI) / 180.f)
27 : #define RAD2DEG( angle ) ((angle) * 180.f / static_cast<float>(M_PI))
28 :
29 : namespace eq
30 : {
31 : namespace fabric
32 : {
33 7247 : Projection::Projection()
34 : : origin( 0.f, 0.f, 0.f ),
35 : distance( 1.f ),
36 : fov( 77.3196f, 53.1301f ),
37 7247 : hpr( 0.f, 0.f, 0.f )
38 7247 : {}
39 :
40 0 : void Projection::resizeHorizontal( const float ratio )
41 : {
42 0 : if( ratio == 1.f || ratio < 0.f )
43 0 : return;
44 :
45 : //const float newWidth_2 = ratio * distance * tanf(DEG2RAD( .5f * fov[1] ));
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 755 : Projection& Projection::operator = ( const Wall& wall )
61 : {
62 755 : Vector3f u = wall.bottomRight - wall.bottomLeft;
63 755 : Vector3f v = wall.topLeft - wall.bottomLeft;
64 755 : const float width = u.normalize();
65 755 : const float height = v.normalize();
66 :
67 755 : Vector3f w;
68 755 : w.cross( u, v );
69 :
70 755 : const Vector3f center( (wall.bottomRight[0] + wall.topLeft[0]) * 0.5f,
71 755 : (wall.bottomRight[1] + wall.topLeft[1]) * 0.5f,
72 2265 : (wall.bottomRight[2] + wall.topLeft[2]) * 0.5f );
73 :
74 755 : if ( distance <= std::numeric_limits< float >::epsilon( ))
75 0 : distance = center.length();
76 :
77 755 : Matrix3f mat;
78 755 : mat.array[0] = u[0];
79 755 : mat.array[1] = u[1];
80 755 : mat.array[2] = u[2];
81 :
82 755 : mat.array[3] = v[0];
83 755 : mat.array[4] = v[1];
84 755 : mat.array[5] = v[2];
85 :
86 755 : mat.array[6] = w[0];
87 755 : mat.array[7] = w[1];
88 755 : mat.array[8] = w[2];
89 :
90 755 : fov[0] = RAD2DEG( atanf(0.5f * width / distance )) * 2.0f;
91 755 : fov[1] = RAD2DEG( atanf(0.5f * height / distance )) * 2.0f;
92 :
93 755 : hpr[0] = -asinf( mat.array[2] );
94 755 : const float cosH = cosf(hpr[0]);
95 755 : hpr[0] = RAD2DEG(hpr[0]);
96 :
97 755 : if( fabs( cosH ) > std::numeric_limits< float >::epsilon( ))
98 : {
99 738 : float tr_x = mat.array[8] / cosH;
100 738 : float tr_y = -mat.array[5] / cosH;
101 738 : hpr[1] = RAD2DEG( atan2f( tr_y, tr_x ));
102 :
103 738 : tr_x = mat.array[0] / cosH;
104 738 : tr_y = -mat.array[1] / cosH;
105 738 : hpr[2] = RAD2DEG( atan2f( tr_y, tr_x ));
106 : }
107 : else
108 : {
109 17 : hpr[1] = 0.f;
110 :
111 17 : const float tr_x = mat.array[4];
112 17 : const float tr_y = mat.array[3];
113 :
114 17 : hpr[2] = RAD2DEG( atan2f( tr_y, tr_x ));
115 : }
116 :
117 755 : origin = center - w * distance;
118 755 : return *this;
119 : }
120 :
121 15 : bool Projection::operator == ( const Projection& rhs ) const
122 : {
123 18 : return( origin.equals( rhs.origin, 0.0001f ) &&
124 6 : (fabsf( distance - rhs.distance ) < 0.0001f ) &&
125 21 : fov.equals( rhs.fov, 0.0001f ) &&
126 18 : hpr.equals( rhs.hpr, 0.0001f ));
127 : }
128 :
129 0 : bool Projection::operator != ( const Projection& rhs ) const
130 : {
131 0 : return ( !origin.equals( rhs.origin, 0.0001f ) ||
132 0 : (fabsf(distance - rhs.distance) >= 0.0001f ) ||
133 0 : !fov.equals( rhs.fov, 0.0001f ) ||
134 0 : !hpr.equals( rhs.hpr, 0.0001f ));
135 : }
136 :
137 :
138 3 : std::ostream& operator << ( std::ostream& os, const Projection& projection )
139 : {
140 3 : const std::ios::fmtflags flags = os.flags();
141 3 : os.setf( std::ios::fixed, std::ios::floatfield );
142 :
143 3 : os << "projection" << std::endl
144 3 : << "{" << std::endl << lunchbox::indent
145 6 : << "origin " << projection.origin << std::endl
146 6 : << "distance " << projection.distance << std::endl
147 6 : << "fov " << projection.fov << std::endl
148 6 : << "hpr " << projection.hpr << std::endl
149 3 : << lunchbox::exdent << "}";
150 :
151 3 : os.setf( flags );
152 3 : return os;
153 : }
154 :
155 : }
156 45 : }
|