Merging r41120 through from trunk r41139 into soc-2011-tomato
[blender.git] / source / gameengine / Rasterizer / RAS_FramingManager.cpp
1 /*
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file gameengine/Rasterizer/RAS_FramingManager.cpp
30  *  \ingroup bgerast
31  */
32
33
34 #include "RAS_FramingManager.h"
35 #include "RAS_Rect.h"
36
37         void
38 RAS_FramingManager::
39 ComputeDefaultFrustum(
40         const float camnear,
41         const float camfar,
42         const float lens,
43         const float sensor_x,
44         const float design_aspect_ratio,
45         RAS_FrameFrustum & frustum
46 ){
47                 
48         /*
49          * Magic Blender calculation.
50          * Blender does not give a Field of View as lens but a size
51          * at 16 units away from the lens.
52          * ^Deprecated Comment
53          */
54         float halfSize = (sensor_x / 2.f) * camnear / lens;
55         float sizeX;
56         float sizeY;
57
58         if (design_aspect_ratio > 1.f) {
59                 // halfsize defines the width
60                 sizeX = halfSize;
61                 sizeY = halfSize/design_aspect_ratio;
62         } else {
63                 // halfsize defines the height
64                 sizeX = halfSize * design_aspect_ratio;
65                 sizeY = halfSize;
66         }
67                 
68         frustum.x2 = sizeX;
69         frustum.x1 = -frustum.x2;
70         frustum.y2 = sizeY;
71         frustum.y1 = -frustum.y2;
72         frustum.camnear = camnear;
73         frustum.camfar = camfar;
74 }
75
76         void
77 RAS_FramingManager::
78 ComputeDefaultOrtho(
79         const float camnear,
80         const float camfar,
81         const float scale,
82         const float design_aspect_ratio,
83         RAS_FrameFrustum & frustum
84 )
85 {
86         float halfSize = scale*0.5f;
87         float sizeX;
88         float sizeY;
89
90         if (design_aspect_ratio > 1.f) {
91                 // halfsize defines the width
92                 sizeX = halfSize;
93                 sizeY = halfSize/design_aspect_ratio;
94         } else {
95                 // halfsize defines the height
96                 sizeX = halfSize * design_aspect_ratio;
97                 sizeY = halfSize;
98         }
99                 
100         frustum.x2 = sizeX;
101         frustum.x1 = -frustum.x2;
102         frustum.y2 = sizeY;
103         frustum.y1 = -frustum.y2;
104         frustum.camnear = camnear;
105         frustum.camfar = camfar;
106 }
107
108
109         void
110 RAS_FramingManager::
111 ComputeBestFitViewRect(
112         const RAS_Rect &availableViewport,
113         const float design_aspect_ratio,
114         RAS_Rect &viewport
115 ){
116         // try and honour the aspect ratio when setting the 
117         // drawable area. If we don't do this we are liable
118         // to get a lot of distortion in the rendered image.
119         
120         int width = availableViewport.GetWidth();
121         int height = availableViewport.GetHeight();
122         float window_aspect = float(width)/float(height);
123
124         if (window_aspect < design_aspect_ratio) {
125                 int v_height = (int)(width / design_aspect_ratio); 
126                 int left_over = (height - v_height) / 2; 
127                         
128                 viewport.SetLeft(availableViewport.GetLeft());
129                 viewport.SetBottom(availableViewport.GetBottom() + left_over);
130                 viewport.SetRight(availableViewport.GetLeft() + width);
131                 viewport.SetTop(availableViewport.GetBottom() + left_over + v_height);
132
133         } else {
134                 int v_width = (int)(height * design_aspect_ratio);
135                 int left_over = (width - v_width) / 2; 
136
137                 viewport.SetLeft(availableViewport.GetLeft() + left_over);
138                 viewport.SetBottom(availableViewport.GetBottom());
139                 viewport.SetRight(availableViewport.GetLeft() + v_width + left_over);
140                 viewport.SetTop(availableViewport.GetBottom() + height);
141         }
142 }
143
144         void
145 RAS_FramingManager::
146 ComputeViewport(
147         const RAS_FrameSettings &settings,
148         const RAS_Rect &availableViewport,
149         RAS_Rect &viewport
150 ){
151
152         RAS_FrameSettings::RAS_FrameType type = settings.FrameType();
153         const int winx = availableViewport.GetWidth();
154         const int winy = availableViewport.GetHeight();
155
156         const float design_width = float(settings.DesignAspectWidth());
157         const float design_height = float(settings.DesignAspectHeight());
158
159         float design_aspect_ratio = float(1);
160
161         if (design_height == float(0)) {
162                 // well this is ill defined 
163                 // lets just scale the thing
164
165                 type = RAS_FrameSettings::e_frame_scale;
166         } else {
167                 design_aspect_ratio = design_width/design_height;
168         }
169
170         switch (type) {
171
172                 case RAS_FrameSettings::e_frame_scale :
173                 case RAS_FrameSettings::e_frame_extend:
174                 {
175                         viewport.SetLeft(availableViewport.GetLeft());
176                         viewport.SetBottom(availableViewport.GetBottom());
177                         viewport.SetRight(availableViewport.GetLeft() + int(winx));
178                         viewport.SetTop(availableViewport.GetBottom() + int(winy));
179
180                         break;
181                 }
182
183                 case RAS_FrameSettings::e_frame_bars:
184                 {
185                         ComputeBestFitViewRect(
186                                 availableViewport,
187                                 design_aspect_ratio,    
188                                 viewport
189                         );
190                 
191                         break;
192                 }
193                 default :
194                         break;
195         }
196 }
197
198         void
199 RAS_FramingManager::
200 ComputeFrustum(
201         const RAS_FrameSettings &settings,
202         const RAS_Rect &availableViewport,
203         const RAS_Rect &viewport,
204         const float lens,
205         const float sensor_x,
206         const float camnear,
207         const float camfar,
208         RAS_FrameFrustum &frustum
209 ){
210
211         RAS_FrameSettings::RAS_FrameType type = settings.FrameType();
212
213         const float design_width = float(settings.DesignAspectWidth());
214         const float design_height = float(settings.DesignAspectHeight());
215
216         float design_aspect_ratio = float(1);
217
218         if (design_height == float(0)) {
219                 // well this is ill defined 
220                 // lets just scale the thing
221
222                 type = RAS_FrameSettings::e_frame_scale;
223         } else {
224                 design_aspect_ratio = design_width/design_height;
225         }
226         
227         ComputeDefaultFrustum(
228                 camnear,
229                 camfar,
230                 lens,
231                 sensor_x,
232                 design_aspect_ratio,
233                 frustum
234         );
235
236         switch (type) {
237
238                 case RAS_FrameSettings::e_frame_extend:
239                 {
240                         RAS_Rect vt;
241                         ComputeBestFitViewRect(
242                                 availableViewport,
243                                 design_aspect_ratio,    
244                                 vt
245                         );
246
247                         // now scale the calculated frustum by the difference
248                         // between vt and the viewport in each axis.
249                         // These are always > 1
250
251                         float x_scale = float(viewport.GetWidth())/float(vt.GetWidth());
252                         float y_scale = float(viewport.GetHeight())/float(vt.GetHeight());
253
254                         frustum.x1 *= x_scale;
255                         frustum.x2 *= x_scale;
256                         frustum.y1 *= y_scale;
257                         frustum.y2 *= y_scale;
258         
259                         break;
260                 }       
261                 case RAS_FrameSettings::e_frame_scale :
262                 case RAS_FrameSettings::e_frame_bars:
263                 default :
264                         break;
265         }
266 }       
267
268         void
269 RAS_FramingManager::
270         ComputeOrtho(
271                 const RAS_FrameSettings &settings,
272                 const RAS_Rect &availableViewport,
273                 const RAS_Rect &viewport,
274                 const float scale,
275                 const float camnear,
276                 const float camfar,
277                 RAS_FrameFrustum &frustum
278         )
279 {
280         RAS_FrameSettings::RAS_FrameType type = settings.FrameType();
281
282         const float design_width = float(settings.DesignAspectWidth());
283         const float design_height = float(settings.DesignAspectHeight());
284
285         float design_aspect_ratio = float(1);
286
287         if (design_height == float(0)) {
288                 // well this is ill defined 
289                 // lets just scale the thing
290                 type = RAS_FrameSettings::e_frame_scale;
291         } else {
292                 design_aspect_ratio = design_width/design_height;
293         }
294
295         
296         ComputeDefaultOrtho(
297                 camnear,
298                 camfar,
299                 scale,
300                 design_aspect_ratio,
301                 frustum
302         );
303
304         switch (type) {
305
306                 case RAS_FrameSettings::e_frame_extend:
307                 {
308                         RAS_Rect vt;
309                         ComputeBestFitViewRect(
310                                 availableViewport,
311                                 design_aspect_ratio,    
312                                 vt
313                         );
314
315                         // now scale the calculated frustum by the difference
316                         // between vt and the viewport in each axis.
317                         // These are always > 1
318
319                         float x_scale = float(viewport.GetWidth())/float(vt.GetWidth());
320                         float y_scale = float(viewport.GetHeight())/float(vt.GetHeight());
321
322                         frustum.x1 *= x_scale;
323                         frustum.x2 *= x_scale;
324                         frustum.y1 *= y_scale;
325                         frustum.y2 *= y_scale;
326         
327                         break;
328                 }       
329                 case RAS_FrameSettings::e_frame_scale :
330                 case RAS_FrameSettings::e_frame_bars:
331                 default :
332                         break;
333         }
334         
335 }
336
337