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