1 /*
2 
3 *************************************************************************
4 
5 ArmageTron -- Just another Tron Lightcycle Game in 3D.
6 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
7 
8 **************************************************************************
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 
24 ***************************************************************************
25 
26 */
27 
28 #include "rFont.h"
29 #include "rScreen.h"
30 #include "rViewport.h"
31 #include "rConsole.h"
32 #include "tConfiguration.h"
33 
34 #ifndef DEDICATED
35 #include "rGL.h"
36 //#include <GL/glu>
37 #ifdef POWERPAK_DEB
38 #include "PowerPak/powerdraw.h"
39 #endif
40 #endif
41 
42 #ifndef DEDICATED
Select()43 void rViewport::Select(){
44     if (sr_glOut)
45         glViewport (GLsizei(sr_screenWidth*left),
46                     GLsizei(sr_screenHeight*bottom),
47                     GLsizei(sr_screenWidth*width),
48                     GLsizei(sr_screenHeight*height));
49 }
50 #endif
51 
52 
UpDownFOV(REAL fov)53 REAL rViewport::UpDownFOV(REAL fov){
54     REAL ratio=currentScreensetting.aspect*(width*sr_screenWidth)/(height*sr_screenHeight);
55 
56     // clamp ratio to 5/3
57     REAL maxratio = 5.0/3.0;
58     if (ratio > maxratio)
59         ratio = maxratio;
60 
61     return 360*atan(tan(M_PI*fov/360)/ratio)/M_PI;
62 }
63 
Perspective(REAL fov,REAL nnear,REAL ffar)64 void rViewport::Perspective(REAL fov,REAL nnear,REAL ffar){
65 #ifndef DEDICATED
66     if (!sr_glOut)
67         return;
68 
69 #if 1
70     // Jonathan's improved version (fixed again)
71 
72     // the true aspect ratio of the viewport. 16/9, 16/10, 4/3, 5/4 (or halves of that for splitscreen)
73     REAL aspectratio = (width * sr_screenWidth * currentScreensetting.aspect)/(height * sr_screenHeight);
74 
75     // usually, fov is the horizontal fov. However, for widescreen, we want to expand the
76     // horizontal fov without distorting the image in such a way that we don't sacrifice too much of
77     // the vertical fov. For non-widescreen, the following number will be 1, for aspect ratios > 1.5 (semi-widescreen),
78     // it'll be higher.
79     REAL ensureverticalfov = fmax(aspectratio/1.5, 1.0);
80 
81     // calculate the horizontal fov. For widescreen, make it extra wide.
82     REAL xmul = ensureverticalfov * tan((M_PI / 360.0) * fov);
83 
84     // transfer that directly to the vertical fov.
85     REAL ymul = xmul/aspectratio;
86     glMatrixMode(GL_PROJECTION);
87     glFrustum(-nnear * xmul, nnear * xmul, -nnear * ymul, nnear * ymul, nnear, ffar);
88 #endif
89 
90 #if 0 // Z-Man's old and clumsy version
91     REAL ratio=currentScreensetting.aspect*(width*sr_screenWidth)/(height*sr_screenHeight);
92     // REAL udfov=360*atan(tan(M_PI*fov/360)/ratio)/M_PI;
93     REAL udfov=UpDownFOV(fov);
94     glMatrixMode(GL_PROJECTION);
95     gluPerspective(
96         udfov,
97         ratio,
98         nnear,
99         ffar
100     );
101 #endif
102 
103 #endif
104 }
105 
106 rViewport rViewport::s_viewportFullscreen(0,0,1,1);
107 
108 rViewport rViewport::s_viewportTop(0,.5,1,.5);
109 rViewport rViewport::s_viewportBottom(0,0,1,.5);
110 
111 rViewport rViewport::s_viewportLeft(0,0,.5,1);
112 rViewport rViewport::s_viewportRight(.5,0,.5,1);
113 
114 rViewport rViewport::s_viewportTopLeft(0,.5,.5,.5);
115 rViewport rViewport::s_viewportBottomLeft(0,0,.5,.5);
116 rViewport rViewport::s_viewportTopRight(.5,.5,.5,.5);
117 rViewport rViewport::s_viewportBottomRight(.5,0,.5,.5);
118 rViewport rViewport::s_viewportDemonstation(.55,.05,.4,.4);
119 
120 int   sr_viewportBelongsToPlayer[MAX_VIEWPORTS],
121 s_newViewportBelongsToPlayer[MAX_VIEWPORTS];
122 
123 // ***********************************************************
124 
125 
rViewportConfiguration(rViewport * first)126 rViewportConfiguration::rViewportConfiguration(rViewport *first)
127         :num_viewports(1){
128     viewports[0]=first;
129 }
130 
rViewportConfiguration(rViewport * first,rViewport * second)131 rViewportConfiguration::rViewportConfiguration(rViewport *first,
132         rViewport *second)
133         :num_viewports(2){
134     viewports[0]=first;
135     viewports[1]=second;
136 }
137 
rViewportConfiguration(rViewport * first,rViewport * second,rViewport * third)138 rViewportConfiguration::rViewportConfiguration(rViewport *first,
139         rViewport *second,
140         rViewport *third)
141         :num_viewports(3){
142     viewports[0]=first;
143     viewports[1]=second;
144     viewports[2]=third;
145 }
146 
rViewportConfiguration(rViewport * first,rViewport * second,rViewport * third,rViewport * forth)147 rViewportConfiguration::rViewportConfiguration(rViewport *first,
148         rViewport *second,
149         rViewport *third,
150         rViewport *forth)
151         :num_viewports(4){
152     viewports[0]=first;
153     viewports[1]=second;
154     viewports[2]=third;
155     viewports[3]=forth;
156 }
157 
158 #ifndef DEDICATED
Select(int i)159 void rViewportConfiguration::Select(int i){
160     if (i>=0 && i <num_viewports)
161         viewports[i]->Select();
162 }
163 #endif
164 
Port(int i)165 rViewport * rViewportConfiguration::Port(int i){
166     if (i>=0 && i <num_viewports)
167         return viewports[i];
168     else
169         return NULL;
170 }
171 
172 static rViewportConfiguration single_vp(&rViewport::s_viewportFullscreen);
173 static rViewportConfiguration two_vp(&rViewport::s_viewportTop,
174                                      &rViewport::s_viewportBottom);
175 static rViewportConfiguration two_b(&rViewport::s_viewportLeft,
176                                     &rViewport::s_viewportRight);
177 static rViewportConfiguration three_a(&rViewport::s_viewportTop,
178                                       &rViewport::s_viewportBottomLeft,
179                                       &rViewport::s_viewportBottomRight);
180 static rViewportConfiguration three_b(&rViewport::s_viewportTopLeft,
181                                       &rViewport::s_viewportTopRight,
182                                       &rViewport::s_viewportBottom);
183 static rViewportConfiguration four_vp(&rViewport::s_viewportTopLeft,
184                                       &rViewport::s_viewportTopRight,
185                                       &rViewport::s_viewportBottomLeft,
186                                       &rViewport::s_viewportBottomRight);
187 
188 rViewportConfiguration *rViewportConfiguration::s_viewportConfigurations[]={
189             &single_vp,&two_vp,&two_b,&three_a,&three_b,&four_vp};
190 
191 char const * rViewportConfiguration::s_viewportConfigurationNames[]=
192     {"$viewport_conf_name_0",
193      "$viewport_conf_name_1",
194      "$viewport_conf_name_2",
195      "$viewport_conf_name_3",
196      "$viewport_conf_name_4",
197      "$viewport_conf_name_5"};
198 
199 const int  rViewportConfiguration::s_viewportNumConfigurations=6;
200 
201 
202 
203 // *******************************************************
204 //   Player menu
205 // *******************************************************
206 
207 static int conf_num=0;
208 int rViewportConfiguration::next_conf_num=0;
209 
210 static tConfItem<int> confn("VIEWPORT_CONF",
211                             rViewportConfiguration::next_conf_num);
212 
CurrentViewportConfiguration()213 rViewportConfiguration *rViewportConfiguration::CurrentViewportConfiguration(){
214     if (conf_num<0) conf_num=0;
215     if (conf_num>=s_viewportNumConfigurations)
216         conf_num=s_viewportNumConfigurations-1;
217 
218     return s_viewportConfigurations[conf_num];
219 }
220 
221 #ifndef DEDICATED
DemonstrateViewport(tString * titles)222 void rViewportConfiguration::DemonstrateViewport(tString *titles){
223     if (!sr_glOut)
224         return;
225 
226     for(int i=s_viewportConfigurations[next_conf_num]->num_viewports-1;i>=0;i--){
227         rViewport sub(rViewport::s_viewportDemonstation,*(s_viewportConfigurations[next_conf_num]->Port(i)));
228         sub.Select();
229 
230         glDisable(GL_TEXTURE_2D);
231         glDisable(GL_DEPTH_TEST);
232 
233         glColor3f(.1,.1,.4);
234         glRectf(-.9,-.9,.9,.9);
235 
236         glColor3f(.6,.6,.6);
237         glBegin(GL_LINE_LOOP);
238         glVertex2f(-1,-1);
239         glVertex2f(-1,1);
240         glVertex2f(1,1);
241         glVertex2f(1,-1);
242         glEnd();
243 
244         glColor3f(1,1,1);
245         DisplayText(0,0,.15,.5,titles[i]);
246     }
247 
248     rViewport::s_viewportFullscreen.Select();
249 }
250 #endif
251 
252 
CurrentViewport(int i)253 rViewport * rViewportConfiguration::CurrentViewport(int i){
254     return CurrentViewportConfiguration()->Port(i);
255 }
256 
UpdateConf()257 void rViewportConfiguration::UpdateConf(){
258     conf_num = next_conf_num;
259 }
260 
261 
262 static int vpb_dir[MAX_VIEWPORTS];
263 
CorrectViewport(int i,int MAX_PLAYERS)264 void rViewport::CorrectViewport(int i, int MAX_PLAYERS){
265     if (vpb_dir[i]!=1 && vpb_dir[i]!=-1)
266         vpb_dir[i]=1;
267 
268     int starta=rViewportConfiguration::s_viewportConfigurations[rViewportConfiguration::next_conf_num]->num_viewports-1;
269     int startb=rViewportConfiguration::s_viewportConfigurations[     conf_num]->num_viewports-1;
270     if (starta>startb)
271         startb=starta;
272 
273     s_newViewportBelongsToPlayer[i]+=MAX_PLAYERS-vpb_dir[i];
274     s_newViewportBelongsToPlayer[i]%=MAX_PLAYERS;
275 
276     int oldValue = s_newViewportBelongsToPlayer[i];
277 
278     bool again;
279     bool expectChange = false;
280     do{
281         // rotate player assignemnt
282         s_newViewportBelongsToPlayer[i]+=MAX_PLAYERS+vpb_dir[i];
283         s_newViewportBelongsToPlayer[i]%=MAX_PLAYERS;
284 
285         // check for conflicts
286         again=false;
287         for(int j=starta;j>=0;j--)
288             if (i!=j && s_newViewportBelongsToPlayer[i]
289                     ==s_newViewportBelongsToPlayer[j])
290             {
291                 again=true;
292                 expectChange=true;
293             }
294     } while(again);
295 
296     if ( oldValue == s_newViewportBelongsToPlayer[i] && expectChange )
297     {
298         // no change? swap players.
299         s_newViewportBelongsToPlayer[i]+=MAX_PLAYERS+vpb_dir[i];
300         s_newViewportBelongsToPlayer[i]%=MAX_PLAYERS;
301 
302         for(int j=starta;j>=0;j--)
303             if (i!=j && s_newViewportBelongsToPlayer[i]
304                     ==s_newViewportBelongsToPlayer[j])
305             {
306                 s_newViewportBelongsToPlayer[j] = oldValue;
307             }
308     }
309 }
310 
CorrectViewports(int MAX_PLAYERS)311 void rViewport::CorrectViewports(int MAX_PLAYERS){
312     for (int i=rViewportConfiguration::s_viewportConfigurations[conf_num]->num_viewports-1;i>=0;i--)
313         CorrectViewport(i, MAX_PLAYERS);
314 }
315 
316 
Update(int MAX_PLAYERS)317 void rViewport::Update(int MAX_PLAYERS){
318     rViewportConfiguration::UpdateConf();
319     CorrectViewports(MAX_PLAYERS);
320 
321     int i;
322     for(i=MAX_VIEWPORTS-1;i>=0;i--)
323         sr_viewportBelongsToPlayer[i]=s_newViewportBelongsToPlayer[i];
324 }
325 
SetDirectionOfCorrection(int vp,int dir)326 void rViewport::SetDirectionOfCorrection(int vp, int dir){
327     vpb_dir[vp] = dir;
328 }
329 
330 // *******************************************************************************************
331 // *
332 // *	CorrectAspectBottom
333 // *
334 // *******************************************************************************************
335 //!
336 //!		@return
337 //!
338 // *******************************************************************************************
339 
CorrectAspectBottom(void) const340 rViewport rViewport::CorrectAspectBottom( void ) const
341 {
342     rViewport ret( *this );
343     ret.height = width * 4.0 / 3.0;
344 
345     return ret;
346 }
347 
348 
349