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 "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 12112 : Projection::Projection()
34 : : origin( 0.f, 0.f, 0.f ),
35 : distance( 1.f ),
36 : fov( 77.3196f, 53.1301f ),
37 12112 : hpr( 0.f, 0.f, 0.f )
38 12112 : {}
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 1260 : Projection& Projection::operator = ( const Wall& wall )
61 : {
62 1260 : Vector3f u = wall.bottomRight - wall.bottomLeft;
63 1260 : Vector3f v = wall.topLeft - wall.bottomLeft;
64 1260 : const float width = u.normalize();
65 1260 : const float height = v.normalize();
66 :
67 1260 : const Vector3f w = vmml::cross( u, v );
68 1260 : const Vector3f center( (wall.bottomRight[0] + wall.topLeft[0]) * 0.5f,
69 1260 : (wall.bottomRight[1] + wall.topLeft[1]) * 0.5f,
70 3780 : (wall.bottomRight[2] + wall.topLeft[2]) * 0.5f );
71 :
72 1260 : if ( distance <= std::numeric_limits< float >::epsilon( ))
73 0 : distance = center.length();
74 :
75 1260 : Matrix3f mat;
76 1260 : mat.array[0] = u[0];
77 1260 : mat.array[1] = u[1];
78 1260 : mat.array[2] = u[2];
79 :
80 1260 : mat.array[3] = v[0];
81 1260 : mat.array[4] = v[1];
82 1260 : mat.array[5] = v[2];
83 :
84 1260 : mat.array[6] = w[0];
85 1260 : mat.array[7] = w[1];
86 1260 : mat.array[8] = w[2];
87 :
88 1260 : fov[0] = RAD2DEG( atanf(0.5f * width / distance )) * 2.0f;
89 1260 : fov[1] = RAD2DEG( atanf(0.5f * height / distance )) * 2.0f;
90 :
91 1260 : hpr[0] = -asinf( mat.array[2] );
92 1260 : const float cosH = cosf(hpr[0]);
93 1260 : hpr[0] = RAD2DEG(hpr[0]);
94 :
95 1260 : if( fabs( cosH ) > std::numeric_limits< float >::epsilon( ))
96 : {
97 1226 : float tr_x = mat.array[8] / cosH;
98 1226 : float tr_y = -mat.array[5] / cosH;
99 1226 : hpr[1] = RAD2DEG( atan2f( tr_y, tr_x ));
100 :
101 1226 : tr_x = mat.array[0] / cosH;
102 1226 : tr_y = -mat.array[1] / cosH;
103 1226 : 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 1260 : origin = center - w * distance;
116 1260 : return *this;
117 : }
118 :
119 30 : bool Projection::operator == ( const Projection& rhs ) const
120 : {
121 36 : return( origin.equals( rhs.origin, 0.0001f ) &&
122 12 : (fabsf( distance - rhs.distance ) < 0.0001f ) &&
123 42 : fov.equals( rhs.fov, 0.0001f ) &&
124 36 : hpr.equals( rhs.hpr, 0.0001f ));
125 : }
126 :
127 0 : bool Projection::operator != ( const Projection& rhs ) const
128 : {
129 0 : return ( !origin.equals( rhs.origin, 0.0001f ) ||
130 0 : (fabsf(distance - rhs.distance) >= 0.0001f ) ||
131 0 : !fov.equals( rhs.fov, 0.0001f ) ||
132 0 : !hpr.equals( rhs.hpr, 0.0001f ));
133 : }
134 :
135 :
136 6 : std::ostream& operator << ( std::ostream& os, const Projection& projection )
137 : {
138 6 : const std::ios::fmtflags flags = os.flags();
139 6 : os.setf( std::ios::fixed, std::ios::floatfield );
140 :
141 6 : os << "projection" << std::endl
142 6 : << "{" << std::endl << lunchbox::indent
143 12 : << "origin " << projection.origin << std::endl
144 12 : << "distance " << projection.distance << std::endl
145 12 : << "fov " << projection.fov << std::endl
146 12 : << "hpr " << projection.hpr << std::endl
147 6 : << lunchbox::exdent << "}";
148 :
149 6 : os.setf( flags );
150 6 : return os;
151 : }
152 :
153 : }
154 84 : }
|