1 /* Emacs style mode select   -*- C++ -*-
2  *-----------------------------------------------------------------------------
3  *
4  *
5  *  PrBoom: a Doom port merged with LxDoom and LSDLDoom
6  *  based on BOOM, a modified and improved DOOM engine
7  *  Copyright (C) 1999 by
8  *  id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9  *  Copyright (C) 1999-2000 by
10  *  Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11  *  Copyright 2005, 2006 by
12  *  Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  *  02111-1307, USA.
28  *
29  * DESCRIPTION:
30  *
31  *---------------------------------------------------------------------
32  */
33 
34 #include "z_zone.h"
35 #ifdef _WIN32
36 #define WIN32_LEAN_AND_MEAN
37 #include <windows.h>
38 #endif
39 #ifndef CALLBACK
40 #define CALLBACK
41 #endif
42 #include <stdio.h>
43 #include <string.h>
44 #include <math.h>
45 #include <SDL.h>
46 #include <SDL_opengl.h>
47 #include "doomtype.h"
48 #include "w_wad.h"
49 #include "m_argv.h"
50 #include "d_event.h"
51 #include "v_video.h"
52 #include "doomstat.h"
53 #include "r_bsp.h"
54 #include "r_main.h"
55 #include "r_draw.h"
56 #include "r_sky.h"
57 #include "r_plane.h"
58 #include "r_data.h"
59 #include "r_things.h"
60 #include "r_fps.h"
61 #include "p_maputl.h"
62 #include "m_bbox.h"
63 #include "lprintf.h"
64 #include "gl_intern.h"
65 #include "gl_struct.h"
66 
67 extern int tran_filter_pct;
68 
69 #define USE_VERTEX_ARRAYS
70 
71 boolean use_fog=false;
72 
73 int gl_nearclip=5;
74 char *gl_tex_filter_string;
75 int gl_tex_filter;
76 int gl_mipmap_filter;
77 int gl_drawskys=true;
78 int gl_sortsprites=true;
79 int gl_texture_filter_anisotropic = 0;
80 int gl_use_paletted_texture = 0;
81 int gl_use_shared_texture_palette = 0;
82 int gl_paletted_texture = 0;
83 int gl_shared_texture_palette = 0;
84 int gl_sprite_offset;	// item out of floor offset Mead 8/13/03
85 
86 PFNGLCOLORTABLEEXTPROC gld_ColorTableEXT;
87 
88 GLuint gld_DisplayList=0;
89 int fog_density=200;
90 static float extra_red=0.0f;
91 static float extra_green=0.0f;
92 static float extra_blue=0.0f;
93 static float extra_alpha=0.0f;
94 
95 GLfloat gl_whitecolor[4]={1.0f,1.0f,1.0f,1.0f};
96 
97 #define MAP_COEFF 128.0f
98 #define MAP_SCALE (MAP_COEFF*(float)FRACUNIT)
99 
100 /*
101  * lookuptable for lightvalues
102  * calculated as follow:
103  * floatlight=(1.0-exp((light^3)*gamma)) / (1.0-exp(1.0*gamma));
104  * gamma=-0,2;-2,0;-4,0;-6,0;-8,0
105  * light=0,0 .. 1,0
106  */
107 static const float lighttable[5][256] =
108 {
109   {
110     0.00000f,0.00000f,0.00000f,0.00000f,0.00000f,0.00001f,0.00001f,0.00002f,0.00003f,0.00004f,
111     0.00006f,0.00008f,0.00010f,0.00013f,0.00017f,0.00020f,0.00025f,0.00030f,0.00035f,0.00041f,
112     0.00048f,0.00056f,0.00064f,0.00073f,0.00083f,0.00094f,0.00106f,0.00119f,0.00132f,0.00147f,
113     0.00163f,0.00180f,0.00198f,0.00217f,0.00237f,0.00259f,0.00281f,0.00305f,0.00331f,0.00358f,
114     0.00386f,0.00416f,0.00447f,0.00479f,0.00514f,0.00550f,0.00587f,0.00626f,0.00667f,0.00710f,
115     0.00754f,0.00800f,0.00848f,0.00898f,0.00950f,0.01003f,0.01059f,0.01117f,0.01177f,0.01239f,
116     0.01303f,0.01369f,0.01437f,0.01508f,0.01581f,0.01656f,0.01734f,0.01814f,0.01896f,0.01981f,
117     0.02069f,0.02159f,0.02251f,0.02346f,0.02444f,0.02544f,0.02647f,0.02753f,0.02862f,0.02973f,
118     0.03088f,0.03205f,0.03325f,0.03448f,0.03575f,0.03704f,0.03836f,0.03971f,0.04110f,0.04252f,
119     0.04396f,0.04545f,0.04696f,0.04851f,0.05009f,0.05171f,0.05336f,0.05504f,0.05676f,0.05852f,
120     0.06031f,0.06214f,0.06400f,0.06590f,0.06784f,0.06981f,0.07183f,0.07388f,0.07597f,0.07810f,
121     0.08027f,0.08248f,0.08473f,0.08702f,0.08935f,0.09172f,0.09414f,0.09659f,0.09909f,0.10163f,
122     0.10421f,0.10684f,0.10951f,0.11223f,0.11499f,0.11779f,0.12064f,0.12354f,0.12648f,0.12946f,
123     0.13250f,0.13558f,0.13871f,0.14188f,0.14511f,0.14838f,0.15170f,0.15507f,0.15850f,0.16197f,
124     0.16549f,0.16906f,0.17268f,0.17635f,0.18008f,0.18386f,0.18769f,0.19157f,0.19551f,0.19950f,
125     0.20354f,0.20764f,0.21179f,0.21600f,0.22026f,0.22458f,0.22896f,0.23339f,0.23788f,0.24242f,
126     0.24702f,0.25168f,0.25640f,0.26118f,0.26602f,0.27091f,0.27587f,0.28089f,0.28596f,0.29110f,
127     0.29630f,0.30156f,0.30688f,0.31226f,0.31771f,0.32322f,0.32879f,0.33443f,0.34013f,0.34589f,
128     0.35172f,0.35761f,0.36357f,0.36960f,0.37569f,0.38185f,0.38808f,0.39437f,0.40073f,0.40716f,
129     0.41366f,0.42022f,0.42686f,0.43356f,0.44034f,0.44718f,0.45410f,0.46108f,0.46814f,0.47527f,
130     0.48247f,0.48974f,0.49709f,0.50451f,0.51200f,0.51957f,0.52721f,0.53492f,0.54271f,0.55058f,
131     0.55852f,0.56654f,0.57463f,0.58280f,0.59105f,0.59937f,0.60777f,0.61625f,0.62481f,0.63345f,
132     0.64217f,0.65096f,0.65984f,0.66880f,0.67783f,0.68695f,0.69615f,0.70544f,0.71480f,0.72425f,
133     0.73378f,0.74339f,0.75308f,0.76286f,0.77273f,0.78268f,0.79271f,0.80283f,0.81304f,0.82333f,
134     0.83371f,0.84417f,0.85472f,0.86536f,0.87609f,0.88691f,0.89781f,0.90880f,0.91989f,0.93106f,
135     0.94232f,0.95368f,0.96512f,0.97665f,0.98828f,1.00000
136   },
137   {
138     0.00000f,0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00003f,0.00005f,0.00007f,0.00010f,
139     0.00014f,0.00019f,0.00024f,0.00031f,0.00038f,0.00047f,0.00057f,0.00069f,0.00081f,0.00096f,
140     0.00112f,0.00129f,0.00148f,0.00170f,0.00193f,0.00218f,0.00245f,0.00274f,0.00306f,0.00340f,
141     0.00376f,0.00415f,0.00456f,0.00500f,0.00547f,0.00597f,0.00649f,0.00704f,0.00763f,0.00825f,
142     0.00889f,0.00957f,0.01029f,0.01104f,0.01182f,0.01264f,0.01350f,0.01439f,0.01532f,0.01630f,
143     0.01731f,0.01836f,0.01945f,0.02058f,0.02176f,0.02298f,0.02424f,0.02555f,0.02690f,0.02830f,
144     0.02974f,0.03123f,0.03277f,0.03436f,0.03600f,0.03768f,0.03942f,0.04120f,0.04304f,0.04493f,
145     0.04687f,0.04886f,0.05091f,0.05301f,0.05517f,0.05738f,0.05964f,0.06196f,0.06434f,0.06677f,
146     0.06926f,0.07181f,0.07441f,0.07707f,0.07979f,0.08257f,0.08541f,0.08831f,0.09126f,0.09428f,
147     0.09735f,0.10048f,0.10368f,0.10693f,0.11025f,0.11362f,0.11706f,0.12056f,0.12411f,0.12773f,
148     0.13141f,0.13515f,0.13895f,0.14281f,0.14673f,0.15072f,0.15476f,0.15886f,0.16303f,0.16725f,
149     0.17153f,0.17587f,0.18028f,0.18474f,0.18926f,0.19383f,0.19847f,0.20316f,0.20791f,0.21272f,
150     0.21759f,0.22251f,0.22748f,0.23251f,0.23760f,0.24274f,0.24793f,0.25318f,0.25848f,0.26383f,
151     0.26923f,0.27468f,0.28018f,0.28573f,0.29133f,0.29697f,0.30266f,0.30840f,0.31418f,0.32001f,
152     0.32588f,0.33179f,0.33774f,0.34374f,0.34977f,0.35585f,0.36196f,0.36810f,0.37428f,0.38050f,
153     0.38675f,0.39304f,0.39935f,0.40570f,0.41207f,0.41847f,0.42490f,0.43136f,0.43784f,0.44434f,
154     0.45087f,0.45741f,0.46398f,0.47057f,0.47717f,0.48379f,0.49042f,0.49707f,0.50373f,0.51041f,
155     0.51709f,0.52378f,0.53048f,0.53718f,0.54389f,0.55061f,0.55732f,0.56404f,0.57075f,0.57747f,
156     0.58418f,0.59089f,0.59759f,0.60429f,0.61097f,0.61765f,0.62432f,0.63098f,0.63762f,0.64425f,
157     0.65086f,0.65746f,0.66404f,0.67060f,0.67714f,0.68365f,0.69015f,0.69662f,0.70307f,0.70948f,
158     0.71588f,0.72224f,0.72857f,0.73488f,0.74115f,0.74739f,0.75359f,0.75976f,0.76589f,0.77199f,
159     0.77805f,0.78407f,0.79005f,0.79599f,0.80189f,0.80774f,0.81355f,0.81932f,0.82504f,0.83072f,
160     0.83635f,0.84194f,0.84747f,0.85296f,0.85840f,0.86378f,0.86912f,0.87441f,0.87964f,0.88482f,
161     0.88995f,0.89503f,0.90005f,0.90502f,0.90993f,0.91479f,0.91959f,0.92434f,0.92903f,0.93366f,
162     0.93824f,0.94276f,0.94723f,0.95163f,0.95598f,0.96027f,0.96451f,0.96868f,0.97280f,0.97686f,
163     0.98086f,0.98481f,0.98869f,0.99252f,0.99629f,1.00000f
164   },
165   {
166     0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00003f,0.00005f,0.00008f,0.00013f,0.00018f,
167     0.00025f,0.00033f,0.00042f,0.00054f,0.00067f,0.00083f,0.00101f,0.00121f,0.00143f,0.00168f,
168     0.00196f,0.00227f,0.00261f,0.00299f,0.00339f,0.00383f,0.00431f,0.00483f,0.00538f,0.00598f,
169     0.00661f,0.00729f,0.00802f,0.00879f,0.00961f,0.01048f,0.01140f,0.01237f,0.01340f,0.01447f,
170     0.01561f,0.01680f,0.01804f,0.01935f,0.02072f,0.02215f,0.02364f,0.02520f,0.02682f,0.02850f,
171     0.03026f,0.03208f,0.03397f,0.03594f,0.03797f,0.04007f,0.04225f,0.04451f,0.04684f,0.04924f,
172     0.05172f,0.05428f,0.05691f,0.05963f,0.06242f,0.06530f,0.06825f,0.07129f,0.07441f,0.07761f,
173     0.08089f,0.08426f,0.08771f,0.09125f,0.09487f,0.09857f,0.10236f,0.10623f,0.11019f,0.11423f,
174     0.11836f,0.12257f,0.12687f,0.13125f,0.13571f,0.14027f,0.14490f,0.14962f,0.15442f,0.15931f,
175     0.16427f,0.16932f,0.17445f,0.17966f,0.18496f,0.19033f,0.19578f,0.20130f,0.20691f,0.21259f,
176     0.21834f,0.22417f,0.23007f,0.23605f,0.24209f,0.24820f,0.25438f,0.26063f,0.26694f,0.27332f,
177     0.27976f,0.28626f,0.29282f,0.29944f,0.30611f,0.31284f,0.31962f,0.32646f,0.33334f,0.34027f,
178     0.34724f,0.35426f,0.36132f,0.36842f,0.37556f,0.38273f,0.38994f,0.39718f,0.40445f,0.41174f,
179     0.41907f,0.42641f,0.43378f,0.44116f,0.44856f,0.45598f,0.46340f,0.47084f,0.47828f,0.48573f,
180     0.49319f,0.50064f,0.50809f,0.51554f,0.52298f,0.53042f,0.53784f,0.54525f,0.55265f,0.56002f,
181     0.56738f,0.57472f,0.58203f,0.58932f,0.59658f,0.60381f,0.61101f,0.61817f,0.62529f,0.63238f,
182     0.63943f,0.64643f,0.65339f,0.66031f,0.66717f,0.67399f,0.68075f,0.68746f,0.69412f,0.70072f,
183     0.70726f,0.71375f,0.72017f,0.72653f,0.73282f,0.73905f,0.74522f,0.75131f,0.75734f,0.76330f,
184     0.76918f,0.77500f,0.78074f,0.78640f,0.79199f,0.79751f,0.80295f,0.80831f,0.81359f,0.81880f,
185     0.82393f,0.82898f,0.83394f,0.83883f,0.84364f,0.84836f,0.85301f,0.85758f,0.86206f,0.86646f,
186     0.87078f,0.87502f,0.87918f,0.88326f,0.88726f,0.89118f,0.89501f,0.89877f,0.90245f,0.90605f,
187     0.90957f,0.91301f,0.91638f,0.91966f,0.92288f,0.92601f,0.92908f,0.93206f,0.93498f,0.93782f,
188     0.94059f,0.94329f,0.94592f,0.94848f,0.95097f,0.95339f,0.95575f,0.95804f,0.96027f,0.96244f,
189     0.96454f,0.96658f,0.96856f,0.97049f,0.97235f,0.97416f,0.97591f,0.97760f,0.97924f,0.98083f,
190     0.98237f,0.98386f,0.98530f,0.98669f,0.98803f,0.98933f,0.99058f,0.99179f,0.99295f,0.99408f,
191     0.99516f,0.99620f,0.99721f,0.99817f,0.99910f,1.00000f
192   },
193   {
194     0.00000f,0.00000f,0.00000f,0.00001f,0.00002f,0.00005f,0.00008f,0.00012f,0.00019f,0.00026f,
195     0.00036f,0.00048f,0.00063f,0.00080f,0.00099f,0.00122f,0.00148f,0.00178f,0.00211f,0.00249f,
196     0.00290f,0.00335f,0.00386f,0.00440f,0.00500f,0.00565f,0.00636f,0.00711f,0.00793f,0.00881f,
197     0.00975f,0.01075f,0.01182f,0.01295f,0.01416f,0.01543f,0.01678f,0.01821f,0.01971f,0.02129f,
198     0.02295f,0.02469f,0.02652f,0.02843f,0.03043f,0.03252f,0.03469f,0.03696f,0.03933f,0.04178f,
199     0.04433f,0.04698f,0.04973f,0.05258f,0.05552f,0.05857f,0.06172f,0.06498f,0.06834f,0.07180f,
200     0.07537f,0.07905f,0.08283f,0.08672f,0.09072f,0.09483f,0.09905f,0.10337f,0.10781f,0.11236f,
201     0.11701f,0.12178f,0.12665f,0.13163f,0.13673f,0.14193f,0.14724f,0.15265f,0.15817f,0.16380f,
202     0.16954f,0.17538f,0.18132f,0.18737f,0.19351f,0.19976f,0.20610f,0.21255f,0.21908f,0.22572f,
203     0.23244f,0.23926f,0.24616f,0.25316f,0.26023f,0.26739f,0.27464f,0.28196f,0.28935f,0.29683f,
204     0.30437f,0.31198f,0.31966f,0.32740f,0.33521f,0.34307f,0.35099f,0.35896f,0.36699f,0.37506f,
205     0.38317f,0.39133f,0.39952f,0.40775f,0.41601f,0.42429f,0.43261f,0.44094f,0.44929f,0.45766f,
206     0.46604f,0.47443f,0.48283f,0.49122f,0.49962f,0.50801f,0.51639f,0.52476f,0.53312f,0.54146f,
207     0.54978f,0.55807f,0.56633f,0.57457f,0.58277f,0.59093f,0.59905f,0.60713f,0.61516f,0.62314f,
208     0.63107f,0.63895f,0.64676f,0.65452f,0.66221f,0.66984f,0.67739f,0.68488f,0.69229f,0.69963f,
209     0.70689f,0.71407f,0.72117f,0.72818f,0.73511f,0.74195f,0.74870f,0.75536f,0.76192f,0.76839f,
210     0.77477f,0.78105f,0.78723f,0.79331f,0.79930f,0.80518f,0.81096f,0.81664f,0.82221f,0.82768f,
211     0.83305f,0.83832f,0.84347f,0.84853f,0.85348f,0.85832f,0.86306f,0.86770f,0.87223f,0.87666f,
212     0.88098f,0.88521f,0.88933f,0.89334f,0.89726f,0.90108f,0.90480f,0.90842f,0.91194f,0.91537f,
213     0.91870f,0.92193f,0.92508f,0.92813f,0.93109f,0.93396f,0.93675f,0.93945f,0.94206f,0.94459f,
214     0.94704f,0.94941f,0.95169f,0.95391f,0.95604f,0.95810f,0.96009f,0.96201f,0.96386f,0.96564f,
215     0.96735f,0.96900f,0.97059f,0.97212f,0.97358f,0.97499f,0.97634f,0.97764f,0.97888f,0.98007f,
216     0.98122f,0.98231f,0.98336f,0.98436f,0.98531f,0.98623f,0.98710f,0.98793f,0.98873f,0.98949f,
217     0.99021f,0.99090f,0.99155f,0.99218f,0.99277f,0.99333f,0.99387f,0.99437f,0.99486f,0.99531f,
218     0.99575f,0.99616f,0.99654f,0.99691f,0.99726f,0.99759f,0.99790f,0.99819f,0.99847f,0.99873f,
219     0.99897f,0.99920f,0.99942f,0.99963f,0.99982f,1.00000f
220   },
221   {
222     0.00000f,0.00000f,0.00000f,0.00001f,0.00003f,0.00006f,0.00010f,0.00017f,0.00025f,0.00035f,
223     0.00048f,0.00064f,0.00083f,0.00106f,0.00132f,0.00163f,0.00197f,0.00237f,0.00281f,0.00330f,
224     0.00385f,0.00446f,0.00513f,0.00585f,0.00665f,0.00751f,0.00845f,0.00945f,0.01054f,0.01170f,
225     0.01295f,0.01428f,0.01569f,0.01719f,0.01879f,0.02048f,0.02227f,0.02415f,0.02614f,0.02822f,
226     0.03042f,0.03272f,0.03513f,0.03765f,0.04028f,0.04303f,0.04589f,0.04887f,0.05198f,0.05520f,
227     0.05855f,0.06202f,0.06561f,0.06933f,0.07318f,0.07716f,0.08127f,0.08550f,0.08987f,0.09437f,
228     0.09900f,0.10376f,0.10866f,0.11369f,0.11884f,0.12414f,0.12956f,0.13512f,0.14080f,0.14662f,
229     0.15257f,0.15865f,0.16485f,0.17118f,0.17764f,0.18423f,0.19093f,0.19776f,0.20471f,0.21177f,
230     0.21895f,0.22625f,0.23365f,0.24117f,0.24879f,0.25652f,0.26435f,0.27228f,0.28030f,0.28842f,
231     0.29662f,0.30492f,0.31329f,0.32175f,0.33028f,0.33889f,0.34756f,0.35630f,0.36510f,0.37396f,
232     0.38287f,0.39183f,0.40084f,0.40989f,0.41897f,0.42809f,0.43723f,0.44640f,0.45559f,0.46479f,
233     0.47401f,0.48323f,0.49245f,0.50167f,0.51088f,0.52008f,0.52927f,0.53843f,0.54757f,0.55668f,
234     0.56575f,0.57479f,0.58379f,0.59274f,0.60164f,0.61048f,0.61927f,0.62799f,0.63665f,0.64524f,
235     0.65376f,0.66220f,0.67056f,0.67883f,0.68702f,0.69511f,0.70312f,0.71103f,0.71884f,0.72655f,
236     0.73415f,0.74165f,0.74904f,0.75632f,0.76348f,0.77053f,0.77747f,0.78428f,0.79098f,0.79756f,
237     0.80401f,0.81035f,0.81655f,0.82264f,0.82859f,0.83443f,0.84013f,0.84571f,0.85117f,0.85649f,
238     0.86169f,0.86677f,0.87172f,0.87654f,0.88124f,0.88581f,0.89026f,0.89459f,0.89880f,0.90289f,
239     0.90686f,0.91071f,0.91445f,0.91807f,0.92157f,0.92497f,0.92826f,0.93143f,0.93450f,0.93747f,
240     0.94034f,0.94310f,0.94577f,0.94833f,0.95081f,0.95319f,0.95548f,0.95768f,0.95980f,0.96183f,
241     0.96378f,0.96565f,0.96744f,0.96916f,0.97081f,0.97238f,0.97388f,0.97532f,0.97669f,0.97801f,
242     0.97926f,0.98045f,0.98158f,0.98266f,0.98369f,0.98467f,0.98560f,0.98648f,0.98732f,0.98811f,
243     0.98886f,0.98958f,0.99025f,0.99089f,0.99149f,0.99206f,0.99260f,0.99311f,0.99359f,0.99404f,
244     0.99446f,0.99486f,0.99523f,0.99559f,0.99592f,0.99623f,0.99652f,0.99679f,0.99705f,0.99729f,
245     0.99751f,0.99772f,0.99792f,0.99810f,0.99827f,0.99843f,0.99857f,0.99871f,0.99884f,0.99896f,
246     0.99907f,0.99917f,0.99926f,0.99935f,0.99943f,0.99951f,0.99958f,0.99964f,0.99970f,0.99975f,
247     0.99980f,0.99985f,0.99989f,0.99993f,0.99997f,1.00000f
248   }
249 };
250 
251 #define gld_CalcLightLevel(lightlevel) (lighttable[usegamma][MAX(MIN((lightlevel),255),0)])
252 
253 /*
254 // experimental new lighting code
255 static float gld_CalcLightLevel(int lightlevel) {
256   if (lightlevel < 192) {
257     lightlevel = lightlevel - ((192 - lightlevel) * 85 / 100);
258   }
259   if (lightlevel < 20)
260     lightlevel = 20;
261   return lightlevel / 255.0;
262 }
263 */
264 
gld_StaticLightAlpha(float light,float alpha)265 static void gld_StaticLightAlpha(float light, float alpha)
266 {
267   player_t *player;
268   player = &players[displayplayer];
269 
270   if (player->fixedcolormap)
271     glColor4f(1.0f, 1.0f, 1.0f, alpha);
272   else
273     glColor4f(light, light, light, alpha);
274 }
275 
276 #define gld_StaticLight(light) gld_StaticLightAlpha(light, 1.0f)
277 
gld_InitExtensions(const char * _extensions)278 static void gld_InitExtensions(const char *_extensions)
279 {
280   char *extensions;
281   char *extension;
282   char *p;
283 
284   if (!_extensions)
285     return;
286 
287   extensions = malloc(strlen(_extensions) + 1);
288   if (!extensions)
289     return;
290   memcpy(extensions, _extensions, strlen(_extensions) + 1);
291 
292   p = extensions;
293   extension = p;
294 
295   do {
296     while ((*p != ' ') && (*p != '\0'))
297       p++;
298     if (*p != '\0')
299       *p++ = '\0';
300     while (*p == ' ')
301       p++;
302 
303     if (strcasecmp(extension, "GL_EXT_texture_filter_anisotropic") == 0)
304       gl_texture_filter_anisotropic = true;
305     else if (strcasecmp(extension, "GL_EXT_paletted_texture") == 0) {
306       if (gl_use_paletted_texture) {
307         gl_paletted_texture = true;
308         gld_ColorTableEXT = SDL_GL_GetProcAddress("glColorTableEXT");
309 	if (gld_ColorTableEXT == NULL)
310 	  gl_paletted_texture = false;
311 	else
312           lprintf(LO_INFO,"using GL_EXT_paletted_texture\n");
313       }
314     }
315     else if (strcasecmp(extension, "GL_EXT_shared_texture_palette") == 0)
316       if (gl_use_shared_texture_palette) {
317         gl_shared_texture_palette = true;
318         gld_ColorTableEXT = SDL_GL_GetProcAddress("glColorTableEXT");
319 	if (gld_ColorTableEXT == NULL)
320 	  gl_shared_texture_palette = false;
321 	else
322           lprintf(LO_INFO,"using GL_EXT_shared_texture_palette\n");
323       }
324 
325     extension = p;
326   } while (*extension != '\0');
327 
328   free(extensions);
329 }
330 
gld_Init(int width,int height)331 void gld_Init(int width, int height)
332 {
333   GLfloat params[4]={0.0f,0.0f,1.0f,0.0f};
334   GLfloat BlackFogColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
335 
336   lprintf(LO_INFO,"GL_VENDOR: %s\n",glGetString(GL_VENDOR));
337   lprintf(LO_INFO,"GL_RENDERER: %s\n",glGetString(GL_RENDERER));
338   lprintf(LO_INFO,"GL_VERSION: %s\n",glGetString(GL_VERSION));
339   lprintf(LO_INFO,"GL_EXTENSIONS:\n");
340   {
341     char ext_name[256];
342     const char *extensions = glGetString(GL_EXTENSIONS);
343     const char *rover = extensions;
344     const char *p = rover;
345 
346     while (*rover)
347     {
348       p = rover;
349       while (*p && *p != ' ')
350         p++;
351       if (*p)
352       {
353         int len = MIN(p-rover, sizeof(ext_name)-1);
354         memset(ext_name, 0, sizeof(ext_name));
355         strncpy(ext_name, rover, len);
356         lprintf(LO_INFO,"\t%s\n", ext_name);
357       }
358       rover = p;
359       while (*rover && *rover == ' ')
360         rover++;
361     }
362   }
363 
364   gld_InitExtensions(glGetString(GL_EXTENSIONS));
365   //gl_shared_texture_palette = false;
366   gld_InitPalettedTextures();
367 
368   glViewport(0, 0, SCREENWIDTH, SCREENHEIGHT);
369 
370   glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
371   glClearDepth(1.0f);
372 
373   glGetIntegerv(GL_MAX_TEXTURE_SIZE,&gld_max_texturesize);
374   //gld_max_texturesize=16;
375   lprintf(LO_INFO,"GL_MAX_TEXTURE_SIZE=%i\n",gld_max_texturesize);
376 
377   glEnable(GL_BLEND);
378   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
379   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
380   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // proff_dis
381   glShadeModel(GL_FLAT);
382   glEnable(GL_TEXTURE_2D);
383   glDepthFunc(GL_LEQUAL);
384   glEnable(GL_ALPHA_TEST);
385   glAlphaFunc(GL_GEQUAL,0.5f);
386   glDisable(GL_CULL_FACE);
387   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
388 
389   glTexGenfv(GL_Q,GL_EYE_PLANE,params);
390   glTexGenf(GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
391   glTexGenf(GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
392   glTexGenf(GL_Q,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
393   glFogi (GL_FOG_MODE, GL_EXP);
394   glFogfv(GL_FOG_COLOR, BlackFogColor);
395   glFogf (GL_FOG_DENSITY, (float)fog_density/1000.0f);
396   glHint (GL_FOG_HINT, GL_NICEST);
397   glFogf (GL_FOG_START, 0.0f);
398   glFogf (GL_FOG_END, 1.0f);
399   if (!strcasecmp(gl_tex_filter_string,"GL_NEAREST_MIPMAP_NEAREST"))
400   {
401     use_mipmapping=true;
402     gl_shared_texture_palette = false;
403     lprintf(LO_INFO,"Using GL_NEAREST for normal textures.\n");
404     lprintf(LO_INFO,"Using GL_NEAREST_MIPMAP_NEAREST for mipmap textures.\n");
405     gl_tex_filter=GL_NEAREST;
406     gl_mipmap_filter=GL_NEAREST_MIPMAP_NEAREST;
407   }
408   else
409   if (!strcasecmp(gl_tex_filter_string,"GL_LINEAR_MIPMAP_NEAREST"))
410   {
411     use_mipmapping=true;
412     gl_shared_texture_palette = false;
413     lprintf(LO_INFO,"Using GL_LINEAR for normal textures.\n");
414     lprintf(LO_INFO,"Using GL_LINEAR_MIPMAP_NEAREST for mipmap textures.\n");
415     gl_tex_filter=GL_LINEAR;
416     gl_mipmap_filter=GL_LINEAR_MIPMAP_NEAREST;
417   }
418   else
419   if (!strcasecmp(gl_tex_filter_string,"GL_NEAREST_MIPMAP_LINEAR"))
420   {
421     use_mipmapping=true;
422     gl_shared_texture_palette = false;
423     lprintf(LO_INFO,"Using GL_NEAREST for normal textures.\n");
424     lprintf(LO_INFO,"Using GL_NEAREST_MIPMAP_LINEAR for mipmap textures.\n");
425     gl_tex_filter=GL_NEAREST;
426     gl_mipmap_filter=GL_NEAREST_MIPMAP_LINEAR;
427   }
428   else
429   if (!strcasecmp(gl_tex_filter_string,"GL_LINEAR_MIPMAP_LINEAR"))
430   {
431     use_mipmapping=true;
432     gl_shared_texture_palette = false;
433     lprintf(LO_INFO,"Using GL_LINEAR for normal textures.\n");
434     lprintf(LO_INFO,"Using GL_LINEAR_MIPMAP_LINEAR for mipmap textures.\n");
435     gl_tex_filter=GL_LINEAR;
436     gl_mipmap_filter=GL_LINEAR_MIPMAP_LINEAR;
437   }
438   else
439   if (!strcasecmp(gl_tex_filter_string,"GL_NEAREST"))
440   {
441     use_mipmapping=false;
442     lprintf(LO_INFO,"Using GL_NEAREST for textures.\n");
443     gl_tex_filter=GL_NEAREST;
444     gl_mipmap_filter=GL_NEAREST;
445   }
446   else
447   {
448     use_mipmapping=false;
449     lprintf(LO_INFO,"Using GL_LINEAR for textures.\n");
450     gl_tex_filter=GL_LINEAR;
451     gl_mipmap_filter=GL_LINEAR;
452   }
453 
454 #ifndef USE_GLU_MIPMAP
455   use_mipmapping = false;
456 #endif
457 
458   if (!strcasecmp(gl_tex_format_string,"GL_RGBA8"))
459   {
460     gl_tex_format=GL_RGBA8;
461     lprintf(LO_INFO,"Using texture format GL_RGBA8.\n");
462   }
463   else
464   if (!strcasecmp(gl_tex_format_string,"GL_RGB5_A1"))
465   {
466     gl_tex_format=GL_RGB5_A1;
467     lprintf(LO_INFO,"Using texture format GL_RGB5_A1.\n");
468   }
469   else
470   if (!strcasecmp(gl_tex_format_string,"GL_RGBA4"))
471   {
472     gl_tex_format=GL_RGBA4;
473     lprintf(LO_INFO,"Using texture format GL_RGBA4.\n");
474   }
475   else
476   if (!strcasecmp(gl_tex_format_string,"GL_RGBA2"))
477   {
478     gl_tex_format=GL_RGBA2;
479     lprintf(LO_INFO,"Using texture format GL_RGBA2.\n");
480   }
481   else
482   {
483     gl_tex_format=GL_RGBA;
484     lprintf(LO_INFO,"Using texture format GL_RGBA.\n");
485   }
486 }
487 
gld_InitCommandLine(void)488 void gld_InitCommandLine(void)
489 {
490 }
491 
492 #define SCALE_X(x)    ((flags & VPT_STRETCH)?((float)x)*(float)SCREENWIDTH/320.0f:(float)x)
493 #define SCALE_Y(y)    ((flags & VPT_STRETCH)?((float)y)*(float)SCREENHEIGHT/200.0f:(float)y)
494 
gld_DrawNumPatch(int x,int y,int lump,int cm,enum patch_translation_e flags)495 void gld_DrawNumPatch(int x, int y, int lump, int cm, enum patch_translation_e flags)
496 {
497   GLTexture *gltexture;
498   float fU1,fU2,fV1,fV2;
499   float width,height;
500   float xpos, ypos;
501 
502   if (flags & VPT_TRANS)
503   {
504     gltexture=gld_RegisterPatch(lump,cm);
505     gld_BindPatch(gltexture, cm);
506   }
507   else
508   {
509     gltexture=gld_RegisterPatch(lump,CR_DEFAULT);
510     gld_BindPatch(gltexture, CR_DEFAULT);
511   }
512   if (!gltexture)
513     return;
514   fV1=0.0f;
515   fV2=(float)gltexture->height/(float)gltexture->tex_height;
516   if (flags & VPT_FLIP)
517   {
518     fU1=(float)gltexture->width/(float)gltexture->tex_width;
519     fU2=0.0f;
520   }
521   else
522   {
523     fU1=0.0f;
524     fU2=(float)gltexture->width/(float)gltexture->tex_width;
525   }
526   xpos=SCALE_X(x-gltexture->leftoffset);
527   ypos=SCALE_Y(y-gltexture->topoffset);
528   width=SCALE_X(gltexture->realtexwidth);
529   height=SCALE_Y(gltexture->realtexheight);
530   glBegin(GL_TRIANGLE_STRIP);
531     glTexCoord2f(fU1, fV1); glVertex2f((xpos),(ypos));
532     glTexCoord2f(fU1, fV2); glVertex2f((xpos),(ypos+height));
533     glTexCoord2f(fU2, fV1); glVertex2f((xpos+width),(ypos));
534     glTexCoord2f(fU2, fV2); glVertex2f((xpos+width),(ypos+height));
535   glEnd();
536 }
537 
538 #undef SCALE_X
539 #undef SCALE_Y
540 
gld_DrawBackground(const char * name)541 void gld_DrawBackground(const char* name)
542 {
543   GLTexture *gltexture;
544   float fU1,fU2,fV1,fV2;
545   int width,height;
546 
547   gltexture=gld_RegisterFlat(R_FlatNumForName(name), false);
548   gld_BindFlat(gltexture);
549   if (!gltexture)
550     return;
551   fU1=0;
552   fV1=0;
553   fU2=(float)SCREENWIDTH/(float)gltexture->realtexwidth;
554   fV2=(float)SCREENHEIGHT/(float)gltexture->realtexheight;
555   width=SCREENWIDTH;
556   height=SCREENHEIGHT;
557   glBegin(GL_TRIANGLE_STRIP);
558     glTexCoord2f(fU1, fV1); glVertex2f((float)(0),(float)(0));
559     glTexCoord2f(fU1, fV2); glVertex2f((float)(0),(float)(0+height));
560     glTexCoord2f(fU2, fV1); glVertex2f((float)(0+width),(float)(0));
561     glTexCoord2f(fU2, fV2); glVertex2f((float)(0+width),(float)(0+height));
562   glEnd();
563 }
564 
gld_DrawLine(int x0,int y0,int x1,int y1,int BaseColor)565 void gld_DrawLine(int x0, int y0, int x1, int y1, int BaseColor)
566 {
567   const unsigned char *playpal=W_CacheLumpName("PLAYPAL");
568 
569   glBindTexture(GL_TEXTURE_2D, 0);
570   last_gltexture = NULL;
571   last_cm = -1;
572   glColor3f((float)playpal[3*BaseColor]/255.0f,
573             (float)playpal[3*BaseColor+1]/255.0f,
574             (float)playpal[3*BaseColor+2]/255.0f);
575   glBegin(GL_LINES);
576     glVertex2i( x0, y0 );
577     glVertex2i( x1, y1 );
578   glEnd();
579   W_UnlockLumpName("PLAYPAL");
580 }
581 
gld_DrawWeapon(int weaponlump,vissprite_t * vis,int lightlevel)582 void gld_DrawWeapon(int weaponlump, vissprite_t *vis, int lightlevel)
583 {
584   GLTexture *gltexture;
585   float fU1,fU2,fV1,fV2;
586   int x1,y1,x2,y2;
587   float scale;
588   float light;
589 
590   gltexture=gld_RegisterPatch(firstspritelump+weaponlump, CR_DEFAULT);
591   if (!gltexture)
592     return;
593   gld_BindPatch(gltexture, CR_DEFAULT);
594   fU1=0;
595   fV1=0;
596   fU2=(float)gltexture->width/(float)gltexture->tex_width;
597   fV2=(float)gltexture->height/(float)gltexture->tex_height;
598   x1=viewwindowx+vis->x1;
599   x2=viewwindowx+vis->x2;
600   scale=((float)vis->scale/(float)FRACUNIT);
601   y1=viewwindowy+centery-(int)(((float)vis->texturemid/(float)FRACUNIT)*scale);
602   y2=y1+(int)((float)gltexture->realtexheight*scale)+1;
603   light=gld_CalcLightLevel(lightlevel);
604 
605   if (viewplayer->mo->flags & MF_SHADOW)
606   {
607     glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
608     glAlphaFunc(GL_GEQUAL,0.1f);
609     //glColor4f(0.2f,0.2f,0.2f,(float)tran_filter_pct/100.0f);
610     glColor4f(0.2f,0.2f,0.2f,0.33f);
611   }
612   else
613   {
614     if (viewplayer->mo->flags & MF_TRANSLUCENT)
615       gld_StaticLightAlpha(light,(float)tran_filter_pct/100.0f);
616     else
617       gld_StaticLight(light);
618   }
619   glBegin(GL_TRIANGLE_STRIP);
620     glTexCoord2f(fU1, fV1); glVertex2f((float)(x1),(float)(y1));
621     glTexCoord2f(fU1, fV2); glVertex2f((float)(x1),(float)(y2));
622     glTexCoord2f(fU2, fV1); glVertex2f((float)(x2),(float)(y1));
623     glTexCoord2f(fU2, fV2); glVertex2f((float)(x2),(float)(y2));
624   glEnd();
625   if(viewplayer->mo->flags & MF_SHADOW)
626   {
627     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
628     glAlphaFunc(GL_GEQUAL,0.5f);
629   }
630   glColor3f(1.0f,1.0f,1.0f);
631 }
632 
gld_FillBlock(int x,int y,int width,int height,int col)633 void gld_FillBlock(int x, int y, int width, int height, int col)
634 {
635   const unsigned char *playpal=W_CacheLumpName("PLAYPAL");
636 
637   glBindTexture(GL_TEXTURE_2D, 0);
638   last_gltexture = NULL;
639   last_cm = -1;
640   glColor3f((float)playpal[3*col]/255.0f,
641             (float)playpal[3*col+1]/255.0f,
642             (float)playpal[3*col+2]/255.0f);
643   glBegin(GL_TRIANGLE_STRIP);
644     glVertex2i( x, y );
645     glVertex2i( x, y+height );
646     glVertex2i( x+width, y );
647     glVertex2i( x+width, y+height );
648   glEnd();
649   glColor3f(1.0f,1.0f,1.0f);
650   W_UnlockLumpName("PLAYPAL");
651 }
652 
gld_SetPalette(int palette)653 void gld_SetPalette(int palette)
654 {
655   static int last_palette = 0;
656   extra_red=0.0f;
657   extra_green=0.0f;
658   extra_blue=0.0f;
659   extra_alpha=0.0f;
660   if (palette < 0)
661     palette = last_palette;
662   last_palette = palette;
663   if (gl_shared_texture_palette) {
664     const unsigned char *playpal;
665     unsigned char pal[1024];
666     int i;
667 
668     playpal = W_CacheLumpName("PLAYPAL");
669     playpal += (768*palette);
670     for (i=0; i<256; i++) {
671       int col;
672 
673       if (fixedcolormap)
674         col = fixedcolormap[i];
675       else if (fullcolormap)
676         col = fullcolormap[i];
677       else
678         col = i;
679       pal[i*4+0] = playpal[col*3+0];
680       pal[i*4+1] = playpal[col*3+1];
681       pal[i*4+2] = playpal[col*3+2];
682       pal[i*4+3] = 255;
683     }
684     pal[transparent_pal_index*4+0]=0;
685     pal[transparent_pal_index*4+1]=0;
686     pal[transparent_pal_index*4+2]=0;
687     pal[transparent_pal_index*4+3]=0;
688     gld_ColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, pal);
689     W_UnlockLumpName("PLAYPAL");
690   } else {
691     if (palette>0)
692     {
693       if (palette<=8)
694       {
695         extra_red=(float)palette/2.0f;
696         extra_green=0.0f;
697         extra_blue=0.0f;
698         extra_alpha=(float)palette/10.0f;
699       }
700       else
701         if (palette<=12)
702         {
703           palette=palette-8;
704           extra_red=(float)palette*1.0f;
705           extra_green=(float)palette*0.8f;
706           extra_blue=(float)palette*0.1f;
707           extra_alpha=(float)palette/11.0f;
708         }
709         else
710           if (palette==13)
711           {
712             extra_red=0.4f;
713             extra_green=1.0f;
714             extra_blue=0.0f;
715             extra_alpha=0.2f;
716           }
717     }
718     if (extra_red>1.0f)
719       extra_red=1.0f;
720     if (extra_green>1.0f)
721       extra_green=1.0f;
722     if (extra_blue>1.0f)
723       extra_blue=1.0f;
724     if (extra_alpha>1.0f)
725       extra_alpha=1.0f;
726   }
727 }
728 
gld_ReadScreen(void)729 unsigned char *gld_ReadScreen(void)
730 {
731   unsigned char *scr;
732   unsigned char buffer[MAX_SCREENWIDTH*3];
733   int i;
734 
735   scr = malloc(SCREENWIDTH * SCREENHEIGHT * 3);
736   if (scr) {
737     glReadPixels(0,0,SCREENWIDTH,SCREENHEIGHT,GL_RGB,GL_UNSIGNED_BYTE,scr);
738     for (i=0; i<SCREENHEIGHT/2; i++) {
739       memcpy(buffer, &scr[i*SCREENWIDTH*3], SCREENWIDTH*3);
740       memcpy(&scr[i*SCREENWIDTH*3],
741           &scr[(SCREENHEIGHT-(i+1))*SCREENWIDTH*3], SCREENWIDTH*3);
742       memcpy(&scr[(SCREENHEIGHT-(i+1))*SCREENWIDTH*3], buffer, SCREENWIDTH*3);
743     }
744   }
745   return scr;
746 }
747 
gld_Set2DMode(void)748 GLvoid gld_Set2DMode(void)
749 {
750   glMatrixMode(GL_MODELVIEW);
751   glLoadIdentity();
752   glMatrixMode(GL_PROJECTION);
753   glLoadIdentity();
754   glOrtho(
755     (GLdouble) 0,
756     (GLdouble) SCREENWIDTH,
757     (GLdouble) SCREENHEIGHT,
758     (GLdouble) 0,
759     (GLdouble) -1.0,
760     (GLdouble) 1.0
761   );
762   glDisable(GL_DEPTH_TEST);
763 }
764 
gld_InitDrawScene(void)765 void gld_InitDrawScene(void)
766 {
767 }
768 
gld_Finish(void)769 void gld_Finish(void)
770 {
771   gld_Set2DMode();
772   glFinish();
773   SDL_GL_SwapBuffers();
774 }
775 
776 /*****************
777  *               *
778  * structs       *
779  *               *
780  *****************/
781 
782 typedef struct
783 {
784   GLfloat x;
785   GLfloat y;
786   GLfloat z;
787 } GLVertex;
788 
789 typedef struct
790 {
791   GLfloat u;
792   GLfloat v;
793 } GLTexcoord;
794 
795 int gld_max_vertexes=0;
796 int gld_num_vertexes=0;
797 GLVertex *gld_vertexes=NULL;
798 GLTexcoord *gld_texcoords=NULL;
799 
gld_AddGlobalVertexes(int count)800 static void gld_AddGlobalVertexes(int count)
801 {
802   if ((gld_num_vertexes+count)>=gld_max_vertexes)
803   {
804     gld_max_vertexes+=count+1024;
805     gld_vertexes=Z_Realloc(gld_vertexes,gld_max_vertexes*sizeof(GLVertex),PU_LEVEL,0);
806     gld_texcoords=Z_Realloc(gld_texcoords,gld_max_vertexes*sizeof(GLTexcoord),PU_LEVEL,0);
807   }
808 }
809 
810 /* GLLoopDef is the struct for one loop. A loop is a list of vertexes
811  * for triangles, which is calculated by the gluTesselator in gld_PrecalculateSector
812  * and in gld_PreprocessCarvedFlat
813  */
814 typedef struct
815 {
816   GLenum mode; // GL_TRIANGLES, GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN
817   int vertexcount; // number of vertexes in this loop
818   int vertexindex; // index into vertex list
819 } GLLoopDef;
820 
821 // GLSector is the struct for a sector with a list of loops.
822 
823 typedef struct
824 {
825   int loopcount; // number of loops for this sector
826   GLLoopDef *loops; // the loops itself
827 } GLSector;
828 
829 typedef struct
830 {
831   GLLoopDef loop; // the loops itself
832 } GLSubSector;
833 
834 typedef struct
835 {
836   float x1,x2;
837   float z1,z2;
838 } GLSeg;
839 
840 GLSeg *gl_segs=NULL;
841 
842 #define GLDWF_TOP 1
843 #define GLDWF_M1S 2
844 #define GLDWF_M2S 3
845 #define GLDWF_BOT 4
846 #define GLDWF_SKY 5
847 #define GLDWF_SKYFLIP 6
848 
849 typedef struct
850 {
851   GLSeg *glseg;
852   float ytop,ybottom;
853   float ul,ur,vt,vb;
854   float light;
855   float alpha;
856   float skyymid;
857   float skyyaw;
858   GLTexture *gltexture;
859   byte flag;
860 } GLWall;
861 
862 typedef struct
863 {
864   int sectornum;
865   float light; // the lightlevel of the flat
866   float uoffs,voffs; // the texture coordinates
867   float z; // the z position of the flat (height)
868   GLTexture *gltexture;
869   boolean ceiling;
870 } GLFlat;
871 
872 typedef struct
873 {
874   int cm;
875   float x,y,z;
876   float vt,vb;
877   float ul,ur;
878   float x1,y1;
879   float x2,y2;
880   float light;
881   fixed_t scale;
882   GLTexture *gltexture;
883   boolean shadow;
884   boolean trans;
885 } GLSprite;
886 
887 typedef enum
888 {
889   GLDIT_NONE,
890   GLDIT_WALL,
891   GLDIT_FLAT,
892   GLDIT_SPRITE
893 } GLDrawItemType;
894 
895 typedef struct
896 {
897   GLDrawItemType itemtype;
898   int itemcount;
899   int firstitemindex;
900   byte rendermarker;
901 } GLDrawItem;
902 
903 typedef struct
904 {
905   GLWall *walls;
906   int num_walls;
907   int max_walls;
908   GLFlat *flats;
909   int num_flats;
910   int max_flats;
911   GLSprite *sprites;
912   int num_sprites;
913   int max_sprites;
914   GLDrawItem *drawitems;
915   int num_drawitems;
916   int max_drawitems;
917 } GLDrawInfo;
918 
919 static GLDrawInfo gld_drawinfo;
920 
921 // this is the list for all sectors to the loops
922 static GLSector *sectorloops;
923 
924 byte rendermarker=0;
925 static byte *sectorrendered; // true if sector rendered (only here for malloc)
926 static byte *segrendered; // true if sector rendered (only here for malloc)
927 
928 static FILE *levelinfo;
929 
930 /*****************************
931  *
932  * FLATS
933  *
934  *****************************/
935 
936 /* proff - 05/15/2000
937  * The idea and algorithm to compute the flats with nodes and subsectors is
938  * originaly from JHexen. I have redone it.
939  */
940 
941 #define FIX2DBL(x)    ((double)(x))
942 #define MAX_CC_SIDES  64
943 
gld_PointOnSide(vertex_t * p,divline_t * d)944 static boolean gld_PointOnSide(vertex_t *p, divline_t *d)
945 {
946   // We'll return false if the point c is on the left side.
947   return ((FIX2DBL(d->y)-FIX2DBL(p->y))*FIX2DBL(d->dx)-(FIX2DBL(d->x)-FIX2DBL(p->x))*FIX2DBL(d->dy) >= 0);
948 }
949 
950 // Lines start-end and fdiv must intersect.
gld_CalcIntersectionVertex(vertex_t * s,vertex_t * e,divline_t * d,vertex_t * i)951 static void gld_CalcIntersectionVertex(vertex_t *s, vertex_t *e, divline_t *d, vertex_t *i)
952 {
953   double ax = FIX2DBL(s->x), ay = FIX2DBL(s->y), bx = FIX2DBL(e->x), by = FIX2DBL(e->y);
954   double cx = FIX2DBL(d->x), cy = FIX2DBL(d->y), dx = cx+FIX2DBL(d->dx), dy = cy+FIX2DBL(d->dy);
955   double r = ((ay-cy)*(dx-cx)-(ax-cx)*(dy-cy)) / ((bx-ax)*(dy-cy)-(by-ay)*(dx-cx));
956   i->x = (fixed_t)((double)s->x + r*((double)e->x-(double)s->x));
957   i->y = (fixed_t)((double)s->y + r*((double)e->y-(double)s->y));
958 }
959 
960 #undef FIX2DBL
961 
962 // Returns a pointer to the list of points. It must be used.
963 //
gld_FlatEdgeClipper(int * numpoints,vertex_t * points,int numclippers,divline_t * clippers)964 static vertex_t *gld_FlatEdgeClipper(int *numpoints, vertex_t *points, int numclippers, divline_t *clippers)
965 {
966   unsigned char sidelist[MAX_CC_SIDES];
967   int       i, k, num = *numpoints;
968 
969   // We'll clip the polygon with each of the divlines. The left side of
970   // each divline is discarded.
971   for(i=0; i<numclippers; i++)
972   {
973     divline_t *curclip = &clippers[i];
974 
975     // First we'll determine the side of each vertex. Points are allowed
976     // to be on the line.
977     for(k=0; k<num; k++)
978       sidelist[k] = gld_PointOnSide(&points[k], curclip);
979 
980     for(k=0; k<num; k++)
981     {
982       int startIdx = k, endIdx = k+1;
983       // Check the end index.
984       if(endIdx == num) endIdx = 0; // Wrap-around.
985       // Clipping will happen when the ends are on different sides.
986       if(sidelist[startIdx] != sidelist[endIdx])
987       {
988         vertex_t newvert;
989 
990         gld_CalcIntersectionVertex(&points[startIdx], &points[endIdx], curclip, &newvert);
991 
992         // Add the new vertex. Also modify the sidelist.
993         points = (vertex_t*)Z_Realloc(points,(++num)*sizeof(vertex_t),PU_LEVEL,0);
994         if(num >= MAX_CC_SIDES)
995           I_Error("gld_FlatEdgeClipper: Too many points in carver");
996 
997         // Make room for the new vertex.
998         memmove(&points[endIdx+1], &points[endIdx],
999           (num - endIdx-1)*sizeof(vertex_t));
1000         memcpy(&points[endIdx], &newvert, sizeof(newvert));
1001 
1002         memmove(&sidelist[endIdx+1], &sidelist[endIdx], num-endIdx-1);
1003         sidelist[endIdx] = 1;
1004 
1005         // Skip over the new vertex.
1006         k++;
1007       }
1008     }
1009 
1010     // Now we must discard the points that are on the wrong side.
1011     for(k=0; k<num; k++)
1012       if(!sidelist[k])
1013       {
1014         memmove(&points[k], &points[k+1], (num - k-1)*sizeof(vertex_t));
1015         memmove(&sidelist[k], &sidelist[k+1], num - k-1);
1016         num--;
1017         k--;
1018       }
1019   }
1020   // Screen out consecutive identical points.
1021   for(i=0; i<num; i++)
1022   {
1023     int previdx = i-1;
1024     if(previdx < 0) previdx = num - 1;
1025     if(points[i].x == points[previdx].x
1026       && points[i].y == points[previdx].y)
1027     {
1028       // This point (i) must be removed.
1029       memmove(&points[i], &points[i+1], sizeof(vertex_t)*(num-i-1));
1030       num--;
1031       i--;
1032     }
1033   }
1034   *numpoints = num;
1035   return points;
1036 }
1037 
gld_FlatConvexCarver(int ssidx,int num,divline_t * list)1038 static void gld_FlatConvexCarver(int ssidx, int num, divline_t *list)
1039 {
1040   subsector_t *ssec=&subsectors[ssidx];
1041   int numclippers = num+ssec->numlines;
1042   divline_t *clippers;
1043   int i, numedgepoints;
1044   vertex_t *edgepoints;
1045 
1046   clippers=(divline_t*)Z_Malloc(numclippers*sizeof(divline_t),PU_LEVEL,0);
1047   if (!clippers)
1048     return;
1049   for(i=0; i<num; i++)
1050   {
1051     clippers[i].x = list[num-i-1].x;
1052     clippers[i].y = list[num-i-1].y;
1053     clippers[i].dx = list[num-i-1].dx;
1054     clippers[i].dy = list[num-i-1].dy;
1055   }
1056   for(i=num; i<numclippers; i++)
1057   {
1058     seg_t *seg = &segs[ssec->firstline+i-num];
1059     clippers[i].x = seg->v1->x;
1060     clippers[i].y = seg->v1->y;
1061     clippers[i].dx = seg->v2->x-seg->v1->x;
1062     clippers[i].dy = seg->v2->y-seg->v1->y;
1063   }
1064 
1065   // Setup the 'worldwide' polygon.
1066   numedgepoints = 4;
1067   edgepoints = (vertex_t*)Z_Malloc(numedgepoints*sizeof(vertex_t),PU_LEVEL,0);
1068 
1069   edgepoints[0].x = INT_MIN;
1070   edgepoints[0].y = INT_MAX;
1071 
1072   edgepoints[1].x = INT_MAX;
1073   edgepoints[1].y = INT_MAX;
1074 
1075   edgepoints[2].x = INT_MAX;
1076   edgepoints[2].y = INT_MIN;
1077 
1078   edgepoints[3].x = INT_MIN;
1079   edgepoints[3].y = INT_MIN;
1080 
1081   // Do some clipping, <snip> <snip>
1082   edgepoints = gld_FlatEdgeClipper(&numedgepoints, edgepoints, numclippers, clippers);
1083 
1084   if(!numedgepoints)
1085   {
1086     if (levelinfo) fprintf(levelinfo, "All carved away: subsector %i - sector %i\n", ssec-subsectors, ssec->sector->iSectorID);
1087   }
1088   else
1089   {
1090     if(numedgepoints >= 3)
1091     {
1092       gld_AddGlobalVertexes(numedgepoints);
1093       if ((gld_vertexes) && (gld_texcoords))
1094       {
1095         int currentsector=ssec->sector->iSectorID;
1096 
1097         sectorloops[ currentsector ].loopcount++;
1098         sectorloops[ currentsector ].loops=Z_Realloc(sectorloops[currentsector].loops,sizeof(GLLoopDef)*sectorloops[currentsector].loopcount, PU_LEVEL, 0);
1099         sectorloops[ currentsector ].loops[ sectorloops[currentsector].loopcount-1 ].mode=GL_TRIANGLE_FAN;
1100         sectorloops[ currentsector ].loops[ sectorloops[currentsector].loopcount-1 ].vertexcount=numedgepoints;
1101         sectorloops[ currentsector ].loops[ sectorloops[currentsector].loopcount-1 ].vertexindex=gld_num_vertexes;
1102 
1103         for(i = 0;  i < numedgepoints; i++)
1104         {
1105           gld_texcoords[gld_num_vertexes].u = ( (float)edgepoints[i].x/(float)FRACUNIT)/64.0f;
1106           gld_texcoords[gld_num_vertexes].v = (-(float)edgepoints[i].y/(float)FRACUNIT)/64.0f;
1107           gld_vertexes[gld_num_vertexes].x = -(float)edgepoints[i].x/MAP_SCALE;
1108           gld_vertexes[gld_num_vertexes].y = 0.0f;
1109           gld_vertexes[gld_num_vertexes].z =  (float)edgepoints[i].y/MAP_SCALE;
1110           gld_num_vertexes++;
1111         }
1112       }
1113     }
1114   }
1115   // We're done, free the edgepoints memory.
1116   Z_Free(edgepoints);
1117   Z_Free(clippers);
1118 }
1119 
gld_CarveFlats(int bspnode,int numdivlines,divline_t * divlines,boolean * sectorclosed)1120 static void gld_CarveFlats(int bspnode, int numdivlines, divline_t *divlines, boolean *sectorclosed)
1121 {
1122   node_t    *nod;
1123   divline_t *childlist, *dl;
1124   int     childlistsize = numdivlines+1;
1125 
1126   // If this is a subsector we are dealing with, begin carving with the
1127   // given list.
1128   if(bspnode & NF_SUBSECTOR)
1129   {
1130     // We have arrived at a subsector. The divline list contains all
1131     // the partition lines that carve out the subsector.
1132     // special case for trivial maps (no nodes, single subsector)
1133     int ssidx = (numnodes != 0) ? bspnode & (~NF_SUBSECTOR) : 0;
1134 
1135     if (!sectorclosed[subsectors[ssidx].sector->iSectorID])
1136       gld_FlatConvexCarver(ssidx, numdivlines, divlines);
1137     return;
1138   }
1139 
1140   // Get a pointer to the node.
1141   nod = nodes + bspnode;
1142 
1143   // Allocate a new list for each child.
1144   childlist = (divline_t*)Z_Malloc(childlistsize*sizeof(divline_t),PU_LEVEL,0);
1145 
1146   // Copy the previous lines.
1147   if(divlines) memcpy(childlist,divlines,numdivlines*sizeof(divline_t));
1148 
1149   dl = childlist + numdivlines;
1150   dl->x = nod->x;
1151   dl->y = nod->y;
1152   // The right child gets the original line (LEFT side clipped).
1153   dl->dx = nod->dx;
1154   dl->dy = nod->dy;
1155   gld_CarveFlats(nod->children[0],childlistsize,childlist,sectorclosed);
1156 
1157   // The left side. We must reverse the line, otherwise the wrong
1158   // side would get clipped.
1159   dl->dx = -nod->dx;
1160   dl->dy = -nod->dy;
1161   gld_CarveFlats(nod->children[1],childlistsize,childlist,sectorclosed);
1162 
1163   // We are finishing with this node, free the allocated list.
1164   Z_Free(childlist);
1165 }
1166 
1167 #ifdef USE_GLU_TESS
1168 
1169 static int currentsector; // the sector which is currently tesselated
1170 
1171 // ntessBegin
1172 //
1173 // called when the tesselation of a new loop starts
1174 
ntessBegin(GLenum type)1175 static void CALLBACK ntessBegin( GLenum type )
1176 {
1177 #ifdef _DEBUG
1178   if (levelinfo)
1179   {
1180     if (type==GL_TRIANGLES)
1181       fprintf(levelinfo, "\t\tBegin: GL_TRIANGLES\n");
1182     else
1183     if (type==GL_TRIANGLE_FAN)
1184       fprintf(levelinfo, "\t\tBegin: GL_TRIANGLE_FAN\n");
1185     else
1186     if (type==GL_TRIANGLE_STRIP)
1187       fprintf(levelinfo, "\t\tBegin: GL_TRIANGLE_STRIP\n");
1188     else
1189       fprintf(levelinfo, "\t\tBegin: unknown\n");
1190   }
1191 #endif
1192   // increase loopcount for currentsector
1193   sectorloops[ currentsector ].loopcount++;
1194   // reallocate to get space for another loop
1195   // PU_LEVEL is used, so this gets freed before a new level is loaded
1196   sectorloops[ currentsector ].loops=Z_Realloc(sectorloops[currentsector].loops,sizeof(GLLoopDef)*sectorloops[currentsector].loopcount, PU_LEVEL, 0);
1197   // set initial values for current loop
1198   // currentloop is -> sectorloops[currentsector].loopcount-1
1199   sectorloops[ currentsector ].loops[ sectorloops[currentsector].loopcount-1 ].mode=type;
1200   sectorloops[ currentsector ].loops[ sectorloops[currentsector].loopcount-1 ].vertexcount=0;
1201   sectorloops[ currentsector ].loops[ sectorloops[currentsector].loopcount-1 ].vertexindex=gld_num_vertexes;
1202 }
1203 
1204 // ntessError
1205 //
1206 // called when the tesselation failes (DEBUG only)
1207 
ntessError(GLenum error)1208 static void CALLBACK ntessError(GLenum error)
1209 {
1210 #ifdef _DEBUG
1211   const GLubyte *estring;
1212   estring = gluErrorString(error);
1213   fprintf(levelinfo, "\t\tTessellation Error: %s\n", estring);
1214 #endif
1215 }
1216 
1217 // ntessCombine
1218 //
1219 // called when the two or more vertexes are on the same coordinate
1220 
ntessCombine(GLdouble coords[3],vertex_t * vert[4],GLfloat w[4],void ** dataOut)1221 static void CALLBACK ntessCombine( GLdouble coords[3], vertex_t *vert[4], GLfloat w[4], void **dataOut )
1222 {
1223 #ifdef _DEBUG
1224   if (levelinfo)
1225   {
1226     fprintf(levelinfo, "\t\tVertexCombine Coords: x %10.5f, y %10.5f z %10.5f\n", coords[0], coords[1], coords[2]);
1227     if (vert[0]) fprintf(levelinfo, "\t\tVertexCombine Vert1 : x %10i, y %10i p %p\n", vert[0]->x>>FRACBITS, vert[0]->y>>FRACBITS, vert[0]);
1228     if (vert[1]) fprintf(levelinfo, "\t\tVertexCombine Vert2 : x %10i, y %10i p %p\n", vert[1]->x>>FRACBITS, vert[1]->y>>FRACBITS, vert[1]);
1229     if (vert[2]) fprintf(levelinfo, "\t\tVertexCombine Vert3 : x %10i, y %10i p %p\n", vert[2]->x>>FRACBITS, vert[2]->y>>FRACBITS, vert[2]);
1230     if (vert[3]) fprintf(levelinfo, "\t\tVertexCombine Vert4 : x %10i, y %10i p %p\n", vert[3]->x>>FRACBITS, vert[3]->y>>FRACBITS, vert[3]);
1231   }
1232 #endif
1233   // just return the first vertex, because all vertexes are on the same coordinate
1234   *dataOut = vert[0];
1235 }
1236 
1237 // ntessVertex
1238 //
1239 // called when a vertex is found
1240 
ntessVertex(vertex_t * vert)1241 static void CALLBACK ntessVertex( vertex_t *vert )
1242 {
1243 #ifdef _DEBUG
1244   if (levelinfo)
1245     fprintf(levelinfo, "\t\tVertex : x %10i, y %10i\n", vert->x>>FRACBITS, vert->y>>FRACBITS);
1246 #endif
1247   // increase vertex count
1248   sectorloops[ currentsector ].loops[ sectorloops[currentsector].loopcount-1 ].vertexcount++;
1249 
1250   // increase vertex count
1251   gld_AddGlobalVertexes(1);
1252   // add the new vertex (vert is the second argument of gluTessVertex)
1253   gld_texcoords[gld_num_vertexes].u=( (float)vert->x/(float)FRACUNIT)/64.0f;
1254   gld_texcoords[gld_num_vertexes].v=(-(float)vert->y/(float)FRACUNIT)/64.0f;
1255   gld_vertexes[gld_num_vertexes].x=-(float)vert->x/MAP_SCALE;
1256   gld_vertexes[gld_num_vertexes].y=0.0f;
1257   gld_vertexes[gld_num_vertexes].z= (float)vert->y/MAP_SCALE;
1258   gld_num_vertexes++;
1259 }
1260 
1261 // ntessEnd
1262 //
1263 // called when the tesselation of a the current loop ends (DEBUG only)
1264 
ntessEnd(void)1265 static void CALLBACK ntessEnd( void )
1266 {
1267 #ifdef _DEBUG
1268   if (levelinfo)
1269     fprintf(levelinfo, "\t\tEnd loopcount %i vertexcount %i\n", sectorloops[currentsector].loopcount, sectorloops[ currentsector ].loops[ sectorloops[currentsector].loopcount-1 ].vertexcount);
1270 #endif
1271 }
1272 
1273 // gld_PrecalculateSector
1274 //
1275 // this calculates the loops for the sector "num"
1276 //
1277 // how does it work?
1278 // first I have to credit Michael 'Kodak' Ryssen for the usage of the
1279 // glu tesselation functions. the rest of this stuff is entirely done by me (proff).
1280 // if there are any similarities, then they are implications of the algorithm.
1281 //
1282 // I'm starting with the first line of the current sector. I take it's ending vertex and
1283 // add it to the tesselator. the current line is marked as used. then I'm searching for
1284 // the next line which connects to the current line. if there is more than one line, I
1285 // choose the one with the smallest angle to the current. if there is no next line, I
1286 // start a new loop and take the first unused line in the sector. after all lines are
1287 // processed, the polygon is tesselated.
1288 
gld_PrecalculateSector(int num)1289 static void gld_PrecalculateSector(int num)
1290 {
1291   int i;
1292   boolean *lineadded=NULL;
1293   int linecount;
1294   int currentline;
1295   int oldline;
1296   int currentloop;
1297   int bestline;
1298   int bestlinecount;
1299   vertex_t *startvertex;
1300   vertex_t *currentvertex;
1301   angle_t lineangle;
1302   angle_t angle;
1303   angle_t bestangle;
1304   sector_t *backsector;
1305   GLUtesselator *tess;
1306   double *v=NULL;
1307   int maxvertexnum;
1308   int vertexnum;
1309 
1310   currentsector=num;
1311   lineadded=Z_Malloc(sectors[num].linecount*sizeof(boolean),PU_LEVEL,0);
1312   if (!lineadded)
1313   {
1314     if (levelinfo) fclose(levelinfo);
1315     return;
1316   }
1317   // init tesselator
1318   tess=gluNewTess();
1319   if (!tess)
1320   {
1321     if (levelinfo) fclose(levelinfo);
1322     Z_Free(lineadded);
1323     return;
1324   }
1325   // set callbacks
1326   gluTessCallback(tess, GLU_TESS_BEGIN, ntessBegin);
1327   gluTessCallback(tess, GLU_TESS_VERTEX, ntessVertex);
1328   gluTessCallback(tess, GLU_TESS_ERROR, ntessError);
1329   gluTessCallback(tess, GLU_TESS_COMBINE, ntessCombine);
1330   gluTessCallback(tess, GLU_TESS_END, ntessEnd);
1331   if (levelinfo) fprintf(levelinfo, "sector %i, %i lines in sector\n", num, sectors[num].linecount);
1332   // remove any line which has both sides in the same sector (i.e. Doom2 Map01 Sector 1)
1333   for (i=0; i<sectors[num].linecount; i++)
1334   {
1335     lineadded[i]=false;
1336     if (sectors[num].lines[i]->sidenum[0]!=NO_INDEX)
1337       if (sectors[num].lines[i]->sidenum[1]!=NO_INDEX)
1338         if (sides[sectors[num].lines[i]->sidenum[0]].sector
1339           ==sides[sectors[num].lines[i]->sidenum[1]].sector)
1340         {
1341           lineadded[i]=true;
1342           if (levelinfo) fprintf(levelinfo, "line %4i (iLineID %4i) has both sides in same sector (removed)\n", i, sectors[num].lines[i]->iLineID);
1343         }
1344   }
1345 
1346   // initialize variables
1347   linecount=sectors[num].linecount;
1348   oldline=0;
1349   currentline=0;
1350   startvertex=sectors[num].lines[currentline]->v2;
1351   currentloop=0;
1352   vertexnum=0;
1353   maxvertexnum=0;
1354   // start tesselator
1355   if (levelinfo) fprintf(levelinfo, "gluTessBeginPolygon\n");
1356   gluTessBeginPolygon(tess, NULL);
1357   if (levelinfo) fprintf(levelinfo, "\tgluTessBeginContour\n");
1358   gluTessBeginContour(tess);
1359   while (linecount)
1360   {
1361     // if there is no connected line, then start new loop
1362     if ((oldline==currentline) || (startvertex==currentvertex))
1363     {
1364       currentline=-1;
1365       for (i=0; i<sectors[num].linecount; i++)
1366         if (!lineadded[i])
1367         {
1368           currentline=i;
1369           currentloop++;
1370           if ((sectors[num].lines[currentline]->sidenum[0]!=NO_INDEX) ? (sides[sectors[num].lines[currentline]->sidenum[0]].sector==&sectors[num]) : false)
1371             startvertex=sectors[num].lines[currentline]->v1;
1372           else
1373             startvertex=sectors[num].lines[currentline]->v2;
1374           if (levelinfo) fprintf(levelinfo, "\tNew Loop %3i\n", currentloop);
1375           if (oldline!=0)
1376           {
1377             if (levelinfo) fprintf(levelinfo, "\tgluTessEndContour\n");
1378             gluTessEndContour(tess);
1379 //            if (levelinfo) fprintf(levelinfo, "\tgluNextContour\n");
1380 //            gluNextContour(tess, GLU_CW);
1381             if (levelinfo) fprintf(levelinfo, "\tgluTessBeginContour\n");
1382             gluTessBeginContour(tess);
1383           }
1384           break;
1385         }
1386     }
1387     if (currentline==-1)
1388       break;
1389     // add current line
1390     lineadded[currentline]=true;
1391     // check if currentsector is on the front side of the line ...
1392     if ((sectors[num].lines[currentline]->sidenum[0]!=NO_INDEX) ? (sides[sectors[num].lines[currentline]->sidenum[0]].sector==&sectors[num]) : false)
1393     {
1394       // v2 is ending vertex
1395       currentvertex=sectors[num].lines[currentline]->v2;
1396       // calculate the angle of this line for use below
1397       lineangle = R_PointToAngle2(sectors[num].lines[currentline]->v1->x,sectors[num].lines[currentline]->v1->y,sectors[num].lines[currentline]->v2->x,sectors[num].lines[currentline]->v2->y);
1398       lineangle=(lineangle>>ANGLETOFINESHIFT)*360/8192;
1399       if (lineangle>=180)
1400         lineangle=lineangle-360;
1401       if (levelinfo) fprintf(levelinfo, "\t\tAdded Line %4i to Loop, iLineID %5i, Angle: %4i, flipped false\n", currentline, sectors[num].lines[currentline]->iLineID, lineangle);
1402     }
1403     else // ... or on the back side
1404     {
1405       // v1 is ending vertex
1406       currentvertex=sectors[num].lines[currentline]->v1;
1407       // calculate the angle of this line for use below
1408       lineangle = R_PointToAngle2(sectors[num].lines[currentline]->v2->x,sectors[num].lines[currentline]->v2->y,sectors[num].lines[currentline]->v1->x,sectors[num].lines[currentline]->v1->y);
1409       lineangle=(lineangle>>ANGLETOFINESHIFT)*360/8192;
1410       if (lineangle>=180)
1411         lineangle=lineangle-360;
1412       if (levelinfo) fprintf(levelinfo, "\t\tAdded Line %4i to Loop, iLineID %5i, Angle: %4i, flipped true\n", currentline, sectors[num].lines[currentline]->iLineID, lineangle);
1413     }
1414     if (vertexnum>=maxvertexnum)
1415     {
1416       maxvertexnum+=512;
1417       v=Z_Realloc(v,maxvertexnum*3*sizeof(double),PU_LEVEL,0);
1418     }
1419     // calculate coordinates for the glu tesselation functions
1420     v[vertexnum*3+0]=-(double)currentvertex->x/(double)MAP_SCALE;
1421     v[vertexnum*3+1]=0.0;
1422     v[vertexnum*3+2]= (double)currentvertex->y/(double)MAP_SCALE;
1423     // add the vertex to the tesselator, currentvertex is the pointer to the vertexlist of doom
1424     // v[vertexnum] is the GLdouble array of the current vertex
1425     if (levelinfo) fprintf(levelinfo, "\t\tgluTessVertex(%i, %i)\n",currentvertex->x>>FRACBITS,currentvertex->y>>FRACBITS);
1426     gluTessVertex(tess, &v[vertexnum*3], currentvertex);
1427     // increase vertexindex
1428     vertexnum++;
1429     // decrease linecount of current sector
1430     linecount--;
1431     // find the next line
1432     oldline=currentline; // if this isn't changed at the end of the search, a new loop will start
1433     bestline=-1; // set to start values
1434     bestlinecount=0;
1435     // set backsector if there is one
1436     if (sectors[num].lines[currentline]->sidenum[1]!=NO_INDEX)
1437       backsector=sides[sectors[num].lines[currentline]->sidenum[1]].sector;
1438     else
1439       backsector=NULL;
1440     // search through all lines of the current sector
1441     for (i=0; i<sectors[num].linecount; i++)
1442       if (!lineadded[i]) // if the line isn't already added ...
1443         // check if one of the vertexes is the same as the current vertex
1444         if ((sectors[num].lines[i]->v1==currentvertex) || (sectors[num].lines[i]->v2==currentvertex))
1445         {
1446           // calculate the angle of this best line candidate
1447           if ((sectors[num].lines[i]->sidenum[0]!=NO_INDEX) ? (sides[sectors[num].lines[i]->sidenum[0]].sector==&sectors[num]) : false)
1448             angle = R_PointToAngle2(sectors[num].lines[i]->v1->x,sectors[num].lines[i]->v1->y,sectors[num].lines[i]->v2->x,sectors[num].lines[i]->v2->y);
1449           else
1450             angle = R_PointToAngle2(sectors[num].lines[i]->v2->x,sectors[num].lines[i]->v2->y,sectors[num].lines[i]->v1->x,sectors[num].lines[i]->v1->y);
1451           angle=(angle>>ANGLETOFINESHIFT)*360/8192;
1452           if (angle>=180)
1453             angle=angle-360;
1454           // check if line is flipped ...
1455           if ((sectors[num].lines[i]->sidenum[0]!=NO_INDEX) ? (sides[sectors[num].lines[i]->sidenum[0]].sector==&sectors[num]) : false)
1456           {
1457             // when the line is not flipped and startvertex is not the currentvertex then skip this line
1458             if (sectors[num].lines[i]->v1!=currentvertex)
1459               continue;
1460           }
1461           else
1462           {
1463             // when the line is flipped and endvertex is not the currentvertex then skip this line
1464             if (sectors[num].lines[i]->v2!=currentvertex)
1465               continue;
1466           }
1467           // set new best line candidate
1468           if (bestline==-1) // if this is the first one ...
1469           {
1470             bestline=i;
1471             bestangle=lineangle-angle;
1472             bestlinecount++;
1473           }
1474           else
1475             // check if the angle between the current line and this best line candidate is smaller then
1476             // the angle of the last candidate
1477             if (D_abs(lineangle-angle)<D_abs(bestangle))
1478             {
1479               bestline=i;
1480               bestangle=lineangle-angle;
1481               bestlinecount++;
1482             }
1483         }
1484     if (bestline!=-1) // if a line is found, make it the current line
1485     {
1486       currentline=bestline;
1487       if (bestlinecount>1)
1488         if (levelinfo) fprintf(levelinfo, "\t\tBestlinecount: %4i\n", bestlinecount);
1489     }
1490   }
1491   // let the tesselator calculate the loops
1492   if (levelinfo) fprintf(levelinfo, "\tgluTessEndContour\n");
1493   gluTessEndContour(tess);
1494   if (levelinfo) fprintf(levelinfo, "gluTessEndPolygon\n");
1495   gluTessEndPolygon(tess);
1496   // clean memory
1497   gluDeleteTess(tess);
1498   Z_Free(v);
1499   Z_Free(lineadded);
1500 }
1501 
1502 #endif /* USE_GLU_TESS */
1503 
1504 /********************************************
1505  * Name     : gld_GetSubSectorVertices      *
1506  * created  : 08/13/00                      *
1507  * modified : 09/18/00, adapted for PrBoom  *
1508  * author   : figgi                         *
1509  * what     : prepares subsectorvertices    *
1510  *            (glnodes only)                *
1511  ********************************************/
1512 
gld_GetSubSectorVertices(boolean * sectorclosed)1513 void gld_GetSubSectorVertices(boolean *sectorclosed)
1514 {
1515   int      i, j;
1516   int      numedgepoints;
1517   subsector_t* ssector;
1518 
1519   for(i = 0; i < numsubsectors; i++)
1520   {
1521     ssector = &subsectors[i];
1522 
1523     if (sectorclosed[ssector->sector->iSectorID])
1524       continue;
1525 
1526     numedgepoints  = ssector->numlines;
1527 
1528     gld_AddGlobalVertexes(numedgepoints);
1529 
1530     if ((gld_vertexes) && (gld_texcoords))
1531     {
1532       int currentsector = ssector->sector->iSectorID;
1533 
1534       sectorloops[currentsector].loopcount++;
1535       sectorloops[currentsector].loops = Z_Realloc(sectorloops[currentsector].loops,sizeof(GLLoopDef)*sectorloops[currentsector].loopcount, PU_LEVEL, 0);
1536       sectorloops[currentsector].loops[sectorloops[currentsector].loopcount-1].mode    = GL_TRIANGLE_FAN;
1537       sectorloops[currentsector].loops[sectorloops[currentsector].loopcount-1].vertexcount = numedgepoints;
1538       sectorloops[currentsector].loops[sectorloops[currentsector].loopcount-1].vertexindex = gld_num_vertexes;
1539       for(j = 0;  j < numedgepoints; j++)
1540       {
1541         gld_texcoords[gld_num_vertexes].u =( (float)(segs[ssector->firstline + j].v1->x)/FRACUNIT)/64.0f;
1542         gld_texcoords[gld_num_vertexes].v =(-(float)(segs[ssector->firstline + j].v1->y)/FRACUNIT)/64.0f;
1543         gld_vertexes[gld_num_vertexes].x = -(float)(segs[ssector->firstline + j].v1->x)/MAP_SCALE;
1544         gld_vertexes[gld_num_vertexes].y = 0.0f;
1545         gld_vertexes[gld_num_vertexes].z =  (float)(segs[ssector->firstline + j].v1->y)/MAP_SCALE;
1546         gld_num_vertexes++;
1547       }
1548     }
1549   }
1550 }
1551 
gld_PrepareSectorSpecialEffects(int num)1552 static void gld_PrepareSectorSpecialEffects(int num)
1553 {
1554   int i;
1555 
1556   // the following is for specialeffects. see r_bsp.c in R_Subsector
1557   sectors[num].no_toptextures=true;
1558   sectors[num].no_bottomtextures=true;
1559   for (i=0; i<sectors[num].linecount; i++)
1560   {
1561     if ( (sectors[num].lines[i]->sidenum[0]!=NO_INDEX) &&
1562          (sectors[num].lines[i]->sidenum[1]!=NO_INDEX) )
1563     {
1564       if (sides[sectors[num].lines[i]->sidenum[0]].toptexture!=NO_TEXTURE)
1565         sectors[num].no_toptextures=false;
1566       if (sides[sectors[num].lines[i]->sidenum[0]].bottomtexture!=NO_TEXTURE)
1567         sectors[num].no_bottomtextures=false;
1568       if (sides[sectors[num].lines[i]->sidenum[1]].toptexture!=NO_TEXTURE)
1569         sectors[num].no_toptextures=false;
1570       if (sides[sectors[num].lines[i]->sidenum[1]].bottomtexture!=NO_TEXTURE)
1571         sectors[num].no_bottomtextures=false;
1572     }
1573     else
1574     {
1575       sectors[num].no_toptextures=false;
1576       sectors[num].no_bottomtextures=false;
1577     }
1578   }
1579 #ifdef _DEBUG
1580   if (sectors[num].no_toptextures)
1581     lprintf(LO_INFO,"Sector %i has no toptextures\n",num);
1582   if (sectors[num].no_bottomtextures)
1583     lprintf(LO_INFO,"Sector %i has no bottomtextures\n",num);
1584 #endif
1585 }
1586 
1587 // gld_PreprocessLevel
1588 //
1589 // this checks all sectors if they are closed and calls gld_PrecalculateSector to
1590 // calculate the loops for every sector
1591 // the idea to check for closed sectors is from DEU. check next commentary
1592 /*
1593       Note from RQ:
1594       This is a very simple idea, but it works!  The first test (above)
1595       checks that all Sectors are closed.  But if a closed set of LineDefs
1596       is moved out of a Sector and has all its "external" SideDefs pointing
1597       to that Sector instead of the new one, then we need a second test.
1598       That's why I check if the SideDefs facing each other are bound to
1599       the same Sector.
1600 
1601       Other note from RQ:
1602       Nowadays, what makes the power of a good editor is its automatic tests.
1603       So, if you are writing another Doom editor, you will probably want
1604       to do the same kind of tests in your program.  Fine, but if you use
1605       these ideas, don't forget to credit DEU...  Just a reminder... :-)
1606 */
1607 // so I credited DEU
1608 
gld_PreprocessSectors(void)1609 void gld_PreprocessSectors(void)
1610 {
1611   boolean *sectorclosed;
1612   int i;
1613 #ifdef USE_GLU_TESS // figgi
1614   char *vertexcheck;
1615   int v1num;
1616   int v2num;
1617   int j;
1618 #endif
1619 
1620 #ifdef _DEBUG
1621   levelinfo=fopen("levelinfo.txt","a");
1622   if (levelinfo)
1623   {
1624     if (gamemode==commercial)
1625       fprintf(levelinfo,"MAP%02i\n",gamemap);
1626     else
1627       fprintf(levelinfo,"E%iM%i\n",gameepisode,gamemap);
1628   }
1629 #endif
1630 
1631   sectorclosed=Z_Malloc(numsectors*sizeof(boolean),PU_LEVEL,0);
1632   if (!sectorclosed)
1633     I_Error("gld_PreprocessSectors: Not enough memory for array sectorclosed");
1634   memset(sectorclosed, 0, sizeof(boolean)*numsectors);
1635 
1636   sectorloops=Z_Malloc(sizeof(GLSector)*numsectors,PU_LEVEL,0);
1637   if (!sectorloops)
1638     I_Error("gld_PreprocessSectors: Not enough memory for array sectorloops");
1639   memset(sectorloops, 0, sizeof(GLSector)*numsectors);
1640 
1641   sectorrendered=Z_Malloc(numsectors*sizeof(byte),PU_LEVEL,0);
1642   if (!sectorrendered)
1643     I_Error("gld_PreprocessSectors: Not enough memory for array sectorrendered");
1644   memset(sectorrendered, 0, numsectors*sizeof(byte));
1645 
1646   segrendered=Z_Malloc(numsegs*sizeof(byte),PU_LEVEL,0);
1647   if (!segrendered)
1648     I_Error("gld_PreprocessSectors: Not enough memory for array segrendered");
1649   memset(segrendered, 0, numsegs*sizeof(byte));
1650 
1651   gld_vertexes=NULL;
1652   gld_texcoords=NULL;
1653   gld_max_vertexes=0;
1654   gld_num_vertexes=0;
1655   gld_AddGlobalVertexes(numvertexes*2);
1656 
1657 #ifdef USE_GLU_TESS
1658   vertexcheck=Z_Malloc(numvertexes*sizeof(char),PU_LEVEL,0);
1659   if (!vertexcheck)
1660   {
1661     if (levelinfo) fclose(levelinfo);
1662     I_Error("gld_PreprocessSectors: Not enough memory for array vertexcheck");
1663     return;
1664   }
1665 
1666   for (i=0; i<numsectors; i++)
1667   {
1668     memset(vertexcheck,0,numvertexes*sizeof(char));
1669     for (j=0; j<sectors[i].linecount; j++)
1670     {
1671       v1num=((int)sectors[i].lines[j]->v1-(int)vertexes)/sizeof(vertex_t);
1672       v2num=((int)sectors[i].lines[j]->v2-(int)vertexes)/sizeof(vertex_t);
1673       if ((v1num>=numvertexes) || (v2num>=numvertexes))
1674         continue;
1675       if (sectors[i].lines[j]->sidenum[0]!=NO_INDEX)
1676         if (sides[sectors[i].lines[j]->sidenum[0]].sector==&sectors[i])
1677         {
1678           vertexcheck[v1num]|=1;
1679           vertexcheck[v2num]|=2;
1680         }
1681       if (sectors[i].lines[j]->sidenum[1]!=NO_INDEX)
1682         if (sides[sectors[i].lines[j]->sidenum[1]].sector==&sectors[i])
1683         {
1684           vertexcheck[v1num]|=2;
1685           vertexcheck[v2num]|=1;
1686         }
1687     }
1688     if (sectors[i].linecount<3)
1689     {
1690 #ifdef _DEBUG
1691       lprintf(LO_ERROR, "sector %i is not closed! %i lines in sector\n", i, sectors[i].linecount);
1692 #endif
1693       if (levelinfo) fprintf(levelinfo, "sector %i is not closed! %i lines in sector\n", i, sectors[i].linecount);
1694       sectorclosed[i]=false;
1695     }
1696     else
1697     {
1698       sectorclosed[i]=true;
1699       for (j=0; j<numvertexes; j++)
1700       {
1701         if ((vertexcheck[j]==1) || (vertexcheck[j]==2))
1702         {
1703 #ifdef _DEBUG
1704           lprintf(LO_ERROR, "sector %i is not closed at vertex %i ! %i lines in sector\n", i, j, sectors[i].linecount);
1705 #endif
1706           if (levelinfo) fprintf(levelinfo, "sector %i is not closed at vertex %i ! %i lines in sector\n", i, j, sectors[i].linecount);
1707           sectorclosed[i]=false;
1708         }
1709       }
1710     }
1711     // figgi -- adapted for glnodes
1712     if (sectorclosed[i])
1713       gld_PrecalculateSector(i);
1714   }
1715   Z_Free(vertexcheck);
1716 #endif /* USE_GLU_TESS */
1717 
1718   for (i=0; i<numsectors; i++)
1719     gld_PrepareSectorSpecialEffects(i);
1720 
1721   // figgi -- adapted for glnodes
1722   if (nodesVersion == 0)
1723     gld_CarveFlats(numnodes-1, 0, 0, sectorclosed);
1724   else
1725     gld_GetSubSectorVertices(sectorclosed);
1726 
1727   if (levelinfo) fclose(levelinfo);
1728   Z_Free(sectorclosed);
1729 }
1730 
1731 static float roll     = 0.0f;
1732 static float yaw      = 0.0f;
1733 static float inv_yaw  = 0.0f;
1734 static float pitch    = 0.0f;
1735 
1736 #define __glPi 3.14159265358979323846
1737 
infinitePerspective(GLdouble fovy,GLdouble aspect,GLdouble znear)1738 static void infinitePerspective(GLdouble fovy, GLdouble aspect, GLdouble znear)
1739 {
1740 	GLdouble left, right, bottom, top;
1741 	GLdouble m[16];
1742 
1743 	top = znear * tan(fovy * __glPi / 360.0);
1744 	bottom = -top;
1745 	left = bottom * aspect;
1746 	right = top * aspect;
1747 
1748 	//qglFrustum(left, right, bottom, top, znear, zfar);
1749 
1750 	m[ 0] = (2 * znear) / (right - left);
1751 	m[ 4] = 0;
1752 	m[ 8] = (right + left) / (right - left);
1753 	m[12] = 0;
1754 
1755 	m[ 1] = 0;
1756 	m[ 5] = (2 * znear) / (top - bottom);
1757 	m[ 9] = (top + bottom) / (top - bottom);
1758 	m[13] = 0;
1759 
1760 	m[ 2] = 0;
1761 	m[ 6] = 0;
1762 	//m[10] = - (zfar + znear) / (zfar - znear);
1763 	//m[14] = - (2 * zfar * znear) / (zfar - znear);
1764 	m[10] = -1;
1765 	m[14] = -2 * znear;
1766 
1767 	m[ 3] = 0;
1768 	m[ 7] = 0;
1769 	m[11] = -1;
1770 	m[15] = 0;
1771 
1772 	glMultMatrixd(m);
1773 }
1774 
gld_StartDrawScene(void)1775 void gld_StartDrawScene(void)
1776 {
1777   float trY ;
1778   float xCamera,yCamera;
1779 
1780   extern int screenblocks;
1781   int height;
1782 
1783   if (gl_shared_texture_palette)
1784     glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1785   gld_SetPalette(-1);
1786 
1787   if (screenblocks == 11)
1788     height = SCREENHEIGHT;
1789   else if (screenblocks == 10)
1790     height = SCREENHEIGHT;
1791   else
1792     height = (screenblocks*SCREENHEIGHT/10) & ~7;
1793 
1794   glViewport(viewwindowx, SCREENHEIGHT-(height+viewwindowy-((height-viewheight)/2)), viewwidth, height);
1795   glScissor(viewwindowx, SCREENHEIGHT-(viewheight+viewwindowy), viewwidth, viewheight);
1796   glEnable(GL_SCISSOR_TEST);
1797   // Player coordinates
1798   xCamera=-(float)viewx/MAP_SCALE;
1799   yCamera=(float)viewy/MAP_SCALE;
1800   trY=(float)viewz/MAP_SCALE;
1801 
1802   yaw=270.0f-(float)(viewangle>>ANGLETOFINESHIFT)*360.0f/FINEANGLES;
1803   inv_yaw=-90.0f+(float)(viewangle>>ANGLETOFINESHIFT)*360.0f/FINEANGLES;
1804 
1805 #ifdef _DEBUG
1806   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1807 #else
1808   glClear(GL_DEPTH_BUFFER_BIT);
1809 #endif
1810 
1811   glEnable(GL_DEPTH_TEST);
1812 
1813   glMatrixMode(GL_PROJECTION);
1814   glLoadIdentity();
1815 
1816   infinitePerspective(64.0f, 320.0f/200.0f, (float)gl_nearclip/100.0f);
1817 
1818   glMatrixMode(GL_MODELVIEW);
1819   glLoadIdentity();
1820   glRotatef(roll,  0.0f, 0.0f, 1.0f);
1821   glRotatef(pitch, 1.0f, 0.0f, 0.0f);
1822   glRotatef(yaw,   0.0f, 1.0f, 0.0f);
1823   glTranslatef(-xCamera, -trY, -yCamera);
1824 
1825   if (use_fog)
1826     glEnable(GL_FOG);
1827   else
1828     glDisable(GL_FOG);
1829   rendermarker++;
1830   gld_drawinfo.num_walls=0;
1831   gld_drawinfo.num_flats=0;
1832   gld_drawinfo.num_sprites=0;
1833   gld_drawinfo.num_drawitems=0;
1834 }
1835 
gld_EndDrawScene(void)1836 void gld_EndDrawScene(void)
1837 {
1838   player_t *player = &players[displayplayer];
1839 
1840   glDisable(GL_POLYGON_SMOOTH);
1841 
1842   glViewport(0, 0, SCREENWIDTH, SCREENHEIGHT);
1843   glDisable(GL_FOG);
1844   gld_Set2DMode();
1845 
1846   if (viewangleoffset <= 1024<<ANGLETOFINESHIFT ||
1847     viewangleoffset >=-1024<<ANGLETOFINESHIFT)
1848   { // don't draw on side views
1849     R_DrawPlayerSprites();
1850   }
1851   if (player->fixedcolormap == 32) {
1852 		glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
1853 		glColor4f(1,1,1,1);
1854     glBindTexture(GL_TEXTURE_2D, 0);
1855     last_gltexture = NULL;
1856     last_cm = -1;
1857     glBegin(GL_TRIANGLE_STRIP);
1858   		glVertex2f( 0.0f, 0.0f);
1859 	  	glVertex2f( 0.0f, (float)SCREENHEIGHT);
1860 		  glVertex2f( (float)SCREENWIDTH, 0.0f);
1861 		  glVertex2f( (float)SCREENWIDTH, (float)SCREENHEIGHT);
1862     glEnd();
1863 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1864   }
1865   if (extra_alpha>0.0f)
1866   {
1867     glDisable(GL_ALPHA_TEST);
1868     glColor4f(extra_red, extra_green, extra_blue, extra_alpha);
1869     glBindTexture(GL_TEXTURE_2D, 0);
1870     last_gltexture = NULL;
1871     last_cm = -1;
1872     glBegin(GL_TRIANGLE_STRIP);
1873       glVertex2f( 0.0f, 0.0f);
1874       glVertex2f( 0.0f, (float)SCREENHEIGHT);
1875       glVertex2f( (float)SCREENWIDTH, 0.0f);
1876       glVertex2f( (float)SCREENWIDTH, (float)SCREENHEIGHT);
1877     glEnd();
1878     glEnable(GL_ALPHA_TEST);
1879   }
1880 
1881   glColor3f(1.0f,1.0f,1.0f);
1882   glDisable(GL_SCISSOR_TEST);
1883   if (gl_shared_texture_palette)
1884     glDisable(GL_SHARED_TEXTURE_PALETTE_EXT);
1885 }
1886 
gld_AddDrawItem(GLDrawItemType itemtype,int itemindex)1887 static void gld_AddDrawItem(GLDrawItemType itemtype, int itemindex)
1888 {
1889   if (gld_drawinfo.num_drawitems>=gld_drawinfo.max_drawitems)
1890   {
1891     gld_drawinfo.max_drawitems+=64;
1892     gld_drawinfo.drawitems=Z_Realloc(gld_drawinfo.drawitems,gld_drawinfo.max_drawitems*sizeof(GLDrawItem),PU_LEVEL,0);
1893     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].itemtype=itemtype;
1894     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].itemcount=1;
1895     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].firstitemindex=itemindex;
1896     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].rendermarker=rendermarker;
1897     return;
1898   }
1899   if (gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].rendermarker!=rendermarker)
1900   {
1901     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].itemtype=GLDIT_NONE;
1902     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].rendermarker=rendermarker;
1903   }
1904   if (gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].itemtype!=itemtype)
1905   {
1906     if (gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].itemtype!=GLDIT_NONE)
1907       gld_drawinfo.num_drawitems++;
1908     if (gld_drawinfo.num_drawitems>=gld_drawinfo.max_drawitems)
1909     {
1910       gld_drawinfo.max_drawitems+=64;
1911       gld_drawinfo.drawitems=Z_Realloc(gld_drawinfo.drawitems,gld_drawinfo.max_drawitems*sizeof(GLDrawItem),PU_LEVEL,0);
1912     }
1913     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].itemtype=itemtype;
1914     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].itemcount=1;
1915     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].firstitemindex=itemindex;
1916     gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].rendermarker=rendermarker;
1917     return;
1918   }
1919   gld_drawinfo.drawitems[gld_drawinfo.num_drawitems].itemcount++;
1920 }
1921 
1922 /*****************
1923  *               *
1924  * Walls         *
1925  *               *
1926  *****************/
1927 
gld_DrawWall(GLWall * wall)1928 static void gld_DrawWall(GLWall *wall)
1929 {
1930   if ( (!gl_drawskys) && (wall->flag>=GLDWF_SKY) )
1931     wall->gltexture=NULL;
1932   gld_BindTexture(wall->gltexture);
1933   if (!wall->gltexture)
1934   {
1935 #ifdef _DEBUG
1936     glColor4f(1.0f,0.0f,0.0f,1.0f);
1937 #endif
1938   }
1939   if (wall->flag>=GLDWF_SKY)
1940   {
1941     if ( wall->gltexture )
1942     {
1943       glMatrixMode(GL_TEXTURE);
1944       glPushMatrix();
1945       if ((wall->flag&GLDWF_SKYFLIP)==GLDWF_SKYFLIP)
1946         glScalef(-128.0f/(float)wall->gltexture->buffer_width,200.0f/320.0f*2.0f,1.0f);
1947       else
1948         glScalef(128.0f/(float)wall->gltexture->buffer_width,200.0f/320.0f*2.0f,1.0f);
1949       glTranslatef(wall->skyyaw,wall->skyymid,0.0f);
1950     }
1951     glBegin(GL_TRIANGLE_STRIP);
1952       glVertex3f(wall->glseg->x1,wall->ytop,wall->glseg->z1);
1953       glVertex3f(wall->glseg->x1,wall->ybottom,wall->glseg->z1);
1954       glVertex3f(wall->glseg->x2,wall->ytop,wall->glseg->z2);
1955       glVertex3f(wall->glseg->x2,wall->ybottom,wall->glseg->z2);
1956     glEnd();
1957     if ( wall->gltexture )
1958     {
1959       glPopMatrix();
1960       glMatrixMode(GL_MODELVIEW);
1961     }
1962   }
1963   else
1964   {
1965     gld_StaticLightAlpha(wall->light, wall->alpha);
1966     glBegin(GL_TRIANGLE_STRIP);
1967       glTexCoord2f(wall->ul,wall->vt); glVertex3f(wall->glseg->x1,wall->ytop,wall->glseg->z1);
1968       glTexCoord2f(wall->ul,wall->vb); glVertex3f(wall->glseg->x1,wall->ybottom,wall->glseg->z1);
1969       glTexCoord2f(wall->ur,wall->vt); glVertex3f(wall->glseg->x2,wall->ytop,wall->glseg->z2);
1970       glTexCoord2f(wall->ur,wall->vb); glVertex3f(wall->glseg->x2,wall->ybottom,wall->glseg->z2);
1971     glEnd();
1972   }
1973 }
1974 
1975 #define LINE seg->linedef
1976 #define CALC_Y_VALUES(w, lineheight, floor_height, ceiling_height)\
1977   (w).ytop=((float)(ceiling_height)/(float)MAP_SCALE)+0.001f;\
1978   (w).ybottom=((float)(floor_height)/(float)MAP_SCALE)-0.001f;\
1979   lineheight=((float)fabs(((ceiling_height)/(float)FRACUNIT)-((floor_height)/(float)FRACUNIT)))
1980 
1981 #define OU(w,seg) (((float)((seg)->sidedef->textureoffset+(seg)->offset)/(float)FRACUNIT)/(float)(w).gltexture->buffer_width)
1982 #define OV(w,seg) (((float)((seg)->sidedef->rowoffset)/(float)FRACUNIT)/(float)(w).gltexture->buffer_height)
1983 #define OV_PEG(w,seg,v_offset) (OV((w),(seg))-(((float)(v_offset)/(float)FRACUNIT)/(float)(w).gltexture->buffer_height))
1984 
1985 #define CALC_TEX_VALUES_TOP(w, seg, peg, linelength, lineheight)\
1986   (w).flag=GLDWF_TOP;\
1987   (w).ul=OU((w),(seg))+(0.0f);\
1988   (w).ur=OU((w),(seg))+((linelength)/(float)(w).gltexture->buffer_width);\
1989   (peg)?\
1990   (\
1991     (w).vb=OV((w),(seg))+((float)(w).gltexture->height/(float)(w).gltexture->tex_height),\
1992     (w).vt=((w).vb-((float)(lineheight)/(float)(w).gltexture->buffer_height))\
1993   ):(\
1994     (w).vt=OV((w),(seg))+(0.0f),\
1995     (w).vb=OV((w),(seg))+((float)(lineheight)/(float)(w).gltexture->buffer_height)\
1996   )
1997 
1998 #define CALC_TEX_VALUES_MIDDLE1S(w, seg, peg, linelength, lineheight)\
1999   (w).flag=GLDWF_M1S;\
2000   (w).ul=OU((w),(seg))+(0.0f);\
2001   (w).ur=OU((w),(seg))+((linelength)/(float)(w).gltexture->buffer_width);\
2002   (peg)?\
2003   (\
2004     (w).vb=OV((w),(seg))+((float)(w).gltexture->height/(float)(w).gltexture->tex_height),\
2005     (w).vt=((w).vb-((float)(lineheight)/(float)(w).gltexture->buffer_height))\
2006   ):(\
2007     (w).vt=OV((w),(seg))+(0.0f),\
2008     (w).vb=OV((w),(seg))+((float)(lineheight)/(float)(w).gltexture->buffer_height)\
2009   )
2010 
2011 #define CALC_TEX_VALUES_MIDDLE2S(w, seg, peg, linelength, lineheight)\
2012   (w).flag=GLDWF_M2S;\
2013   (w).ul=OU((w),(seg))+(0.0f);\
2014   (w).ur=OU((w),(seg))+((linelength)/(float)(w).gltexture->buffer_width);\
2015   (peg)?\
2016   (\
2017     (w).vb=((float)(w).gltexture->height/(float)(w).gltexture->tex_height),\
2018     (w).vt=((w).vb-((float)(lineheight)/(float)(w).gltexture->buffer_height))\
2019   ):(\
2020     (w).vt=(0.0f),\
2021     (w).vb=((float)(lineheight)/(float)(w).gltexture->buffer_height)\
2022   )
2023 
2024 #define CALC_TEX_VALUES_BOTTOM(w, seg, peg, linelength, lineheight, v_offset)\
2025   (w).flag=GLDWF_BOT;\
2026   (w).ul=OU((w),(seg))+(0.0f);\
2027   (w).ur=OU((w),(seg))+((linelength)/(float)(w).gltexture->realtexwidth);\
2028   (peg)?\
2029   (\
2030     (w).vb=OV_PEG((w),(seg),(v_offset))+((float)(w).gltexture->height/(float)(w).gltexture->tex_height),\
2031     (w).vt=((w).vb-((float)(lineheight)/(float)(w).gltexture->buffer_height))\
2032   ):(\
2033     (w).vt=OV((w),(seg))+(0.0f),\
2034     (w).vb=OV((w),(seg))+((float)(lineheight)/(float)(w).gltexture->buffer_height)\
2035   )
2036 
2037 // e6y
2038 // Sky textures with a zero index should be forced
2039 // See third episode of requiem.wad
2040 #define SKYTEXTURE(sky1,sky2)\
2041   if ((sky1) & PL_SKYFLAT)\
2042   {\
2043     const line_t *l = &lines[sky1 & ~PL_SKYFLAT];\
2044     const side_t *s = *l->sidenum + sides;\
2045     wall.gltexture=gld_RegisterTexture(texturetranslation[s->toptexture], false, texturetranslation[s->toptexture]==skytexture);\
2046     wall.skyyaw=-2.0f*((-(float)((viewangle+s->textureoffset)>>ANGLETOFINESHIFT)*360.0f/FINEANGLES)/90.0f);\
2047     wall.skyymid = 200.0f/319.5f*(((float)s->rowoffset/(float)FRACUNIT - 28.0f)/100.0f);\
2048     wall.flag = l->special==272 ? GLDWF_SKY : GLDWF_SKYFLIP;\
2049   }\
2050   else\
2051   if ((sky2) & PL_SKYFLAT)\
2052   {\
2053     const line_t *l = &lines[sky2 & ~PL_SKYFLAT];\
2054     const side_t *s = *l->sidenum + sides;\
2055     wall.gltexture=gld_RegisterTexture(texturetranslation[s->toptexture], false, texturetranslation[s->toptexture]==skytexture);\
2056     wall.skyyaw=-2.0f*((-(float)((viewangle+s->textureoffset)>>ANGLETOFINESHIFT)*360.0f/FINEANGLES)/90.0f);\
2057     wall.skyymid = 200.0f/319.5f*(((float)s->rowoffset/(float)FRACUNIT - 28.0f)/100.0f);\
2058     wall.flag = l->special==272 ? GLDWF_SKY : GLDWF_SKYFLIP;\
2059   }\
2060   else\
2061   {\
2062     wall.gltexture=gld_RegisterTexture(skytexture, false, true);\
2063     wall.skyyaw=-2.0f*((yaw+90.0f)/90.0f);\
2064     wall.skyymid = 200.0f/319.5f*((100.0f)/100.0f);\
2065     wall.flag = GLDWF_SKY;\
2066   };
2067 
2068 #define ADDWALL(wall)\
2069 {\
2070   if (gld_drawinfo.num_walls>=gld_drawinfo.max_walls)\
2071   {\
2072     gld_drawinfo.max_walls+=128;\
2073     gld_drawinfo.walls=Z_Realloc(gld_drawinfo.walls,gld_drawinfo.max_walls*sizeof(GLWall),PU_LEVEL,0);\
2074   }\
2075   gld_AddDrawItem(GLDIT_WALL, gld_drawinfo.num_walls);\
2076   gld_drawinfo.walls[gld_drawinfo.num_walls++]=*wall;\
2077 };
2078 
gld_AddWall(seg_t * seg)2079 void gld_AddWall(seg_t *seg)
2080 {
2081   GLWall wall;
2082   GLTexture *temptex;
2083   sector_t *frontsector;
2084   sector_t *backsector;
2085   sector_t ftempsec; // needed for R_FakeFlat
2086   sector_t btempsec; // needed for R_FakeFlat
2087   float lineheight;
2088   int rellight = 0;
2089 
2090   if (!segrendered)
2091     return;
2092   if (segrendered[seg->iSegID]==rendermarker)
2093     return;
2094   segrendered[seg->iSegID]=rendermarker;
2095   if (!seg->frontsector)
2096     return;
2097   frontsector=R_FakeFlat(seg->frontsector, &ftempsec, NULL, NULL, false); // for boom effects
2098   if (!frontsector)
2099     return;
2100   wall.glseg=&gl_segs[seg->iSegID];
2101 
2102   rellight = seg->linedef->dx==0? +8 : seg->linedef->dy==0 ? -8 : 0;
2103   wall.light=gld_CalcLightLevel(frontsector->lightlevel+rellight+(extralight<<5));
2104   wall.alpha=1.0f;
2105   wall.gltexture=NULL;
2106 
2107   if (!seg->backsector) /* onesided */
2108   {
2109     if (frontsector->ceilingpic==skyflatnum)
2110     {
2111       wall.ytop=255.0f;
2112       wall.ybottom=(float)frontsector->ceilingheight/MAP_SCALE;
2113       SKYTEXTURE(frontsector->sky,frontsector->sky);
2114       ADDWALL(&wall);
2115     }
2116     if (frontsector->floorpic==skyflatnum)
2117     {
2118       wall.ytop=(float)frontsector->floorheight/MAP_SCALE;
2119       wall.ybottom=-255.0f;
2120       SKYTEXTURE(frontsector->sky,frontsector->sky);
2121       ADDWALL(&wall);
2122     }
2123     temptex=gld_RegisterTexture(texturetranslation[seg->sidedef->midtexture], true, false);
2124     if (temptex)
2125     {
2126       wall.gltexture=temptex;
2127       CALC_Y_VALUES(wall, lineheight, frontsector->floorheight, frontsector->ceilingheight);
2128       CALC_TEX_VALUES_MIDDLE1S(
2129         wall, seg, (LINE->flags & ML_DONTPEGBOTTOM)>0,
2130         segs[seg->iSegID].length, lineheight
2131       );
2132       ADDWALL(&wall);
2133     }
2134   }
2135   else /* twosided */
2136   {
2137     int floor_height,ceiling_height;
2138 
2139     backsector=R_FakeFlat(seg->backsector, &btempsec, NULL, NULL, true); // for boom effects
2140     if (!backsector)
2141       return;
2142     /* toptexture */
2143     ceiling_height=frontsector->ceilingheight;
2144     floor_height=backsector->ceilingheight;
2145     if (frontsector->ceilingpic==skyflatnum)
2146     {
2147       wall.ytop=255.0f;
2148       if (
2149           // e6y
2150           // Fix for HOM in the starting area on Memento Mori map29 and on map30.
2151           // old code: (backsector->ceilingheight==backsector->floorheight) &&
2152           (backsector->ceilingheight==backsector->floorheight||(backsector->ceilingheight<=frontsector->floorheight)) &&
2153           (backsector->ceilingpic==skyflatnum)
2154          )
2155       {
2156         wall.ybottom=(float)backsector->floorheight/MAP_SCALE;
2157         SKYTEXTURE(frontsector->sky,backsector->sky);
2158         ADDWALL(&wall);
2159       }
2160       else
2161       {
2162         if ( (texturetranslation[seg->sidedef->toptexture]!=NO_TEXTURE) )
2163         {
2164           // e6y
2165           // It corrects some problem with sky, but I do not remember which one
2166           // old code: wall.ybottom=(float)frontsector->ceilingheight/MAP_SCALE;
2167           wall.ybottom=(float)MAX(frontsector->ceilingheight,backsector->ceilingheight)/MAP_SCALE;
2168 
2169           SKYTEXTURE(frontsector->sky,backsector->sky);
2170           ADDWALL(&wall);
2171         }
2172         else
2173           if ( (backsector->ceilingheight <= frontsector->floorheight) ||
2174                (backsector->ceilingpic != skyflatnum) )
2175           {
2176             wall.ybottom=(float)backsector->ceilingheight/MAP_SCALE;
2177             SKYTEXTURE(frontsector->sky,backsector->sky);
2178             ADDWALL(&wall);
2179           }
2180       }
2181     }
2182     if (floor_height<ceiling_height)
2183     {
2184       if (!((frontsector->ceilingpic==skyflatnum) && (backsector->ceilingpic==skyflatnum)))
2185       {
2186         temptex=gld_RegisterTexture(texturetranslation[seg->sidedef->toptexture], true, false);
2187         if (temptex)
2188         {
2189           wall.gltexture=temptex;
2190           CALC_Y_VALUES(wall, lineheight, floor_height, ceiling_height);
2191           CALC_TEX_VALUES_TOP(
2192             wall, seg, (LINE->flags & (ML_DONTPEGBOTTOM | ML_DONTPEGTOP))==0,
2193             segs[seg->iSegID].length, lineheight
2194           );
2195           ADDWALL(&wall);
2196         }
2197       }
2198     }
2199 
2200     /* midtexture */
2201     //e6y
2202     if (comp[comp_maskedanim])
2203       temptex=gld_RegisterTexture(seg->sidedef->midtexture, true, false);
2204     else
2205       // e6y
2206       // Animated middle textures with a zero index should be forced
2207       // See spacelab.wad (http://www.doomworld.com/idgames/index.php?id=6826)
2208       temptex=gld_RegisterTexture(texturetranslation[seg->sidedef->midtexture], true, true);
2209 
2210     if (temptex && seg->sidedef->midtexture != NO_TEXTURE)
2211     {
2212       wall.gltexture=temptex;
2213       if ( (LINE->flags & ML_DONTPEGBOTTOM) >0)
2214       {
2215         if (seg->backsector->ceilingheight<=seg->frontsector->floorheight)
2216           goto bottomtexture;
2217         floor_height=MAX(seg->frontsector->floorheight,seg->backsector->floorheight)+(seg->sidedef->rowoffset);
2218         ceiling_height=floor_height+(wall.gltexture->realtexheight<<FRACBITS);
2219       }
2220       else
2221       {
2222         if (seg->backsector->ceilingheight<=seg->frontsector->floorheight)
2223           goto bottomtexture;
2224         ceiling_height=MIN(seg->frontsector->ceilingheight,seg->backsector->ceilingheight)+(seg->sidedef->rowoffset);
2225         floor_height=ceiling_height-(wall.gltexture->realtexheight<<FRACBITS);
2226       }
2227       // e6y
2228       // The fix for wrong middle texture drawing
2229       // if it exceeds the boundaries of its floor and ceiling
2230 
2231       /*CALC_Y_VALUES(wall, lineheight, floor_height, ceiling_height);
2232       CALC_TEX_VALUES_MIDDLE2S(
2233         wall, seg, (LINE->flags & ML_DONTPEGBOTTOM)>0,
2234         segs[seg->iSegID].length, lineheight
2235       );*/
2236       {
2237         int floormax, ceilingmin, linelen;
2238         float mip;
2239         mip = (float)wall.gltexture->realtexheight/(float)wall.gltexture->buffer_height;
2240 //        if ( (texturetranslation[seg->sidedef->bottomtexture]!=R_TextureNumForName("-")) )
2241         if (seg->sidedef->bottomtexture)
2242           floormax=MAX(seg->frontsector->floorheight,seg->backsector->floorheight);
2243         else
2244           floormax=floor_height;
2245         if (seg->sidedef->toptexture)
2246           ceilingmin=MIN(seg->frontsector->ceilingheight,seg->backsector->ceilingheight);
2247         else
2248           ceilingmin=ceiling_height;
2249         linelen=abs(ceiling_height-floor_height);
2250         wall.ytop=((float)MIN(ceilingmin, ceiling_height)/(float)MAP_SCALE);
2251         wall.ybottom=((float)MAX(floormax, floor_height)/(float)MAP_SCALE);
2252         wall.flag=GLDWF_M2S;
2253         wall.ul=OU((wall),(seg))+(0.0f);
2254         wall.ur=OU(wall,(seg))+((segs[seg->iSegID].length)/(float)wall.gltexture->buffer_width);
2255         if (floormax<=floor_height)
2256 #ifdef USE_GLU_IMAGESCALE
2257           wall.vb=1.0f;
2258 #else  // USE_GLU_IMAGESCALE
2259           wall.vb=mip*1.0f;
2260 #endif // USE_GLU_IMAGESCALE
2261         else
2262           wall.vb=mip*((float)(ceiling_height - floormax))/linelen;
2263         if (ceilingmin>=ceiling_height)
2264           wall.vt=0.0f;
2265         else
2266           wall.vt=mip*((float)(ceiling_height - ceilingmin))/linelen;
2267       }
2268 
2269       if (seg->linedef->tranlump >= 0 && general_translucency)
2270         wall.alpha=(float)tran_filter_pct/100.0f;
2271       ADDWALL(&wall);
2272       wall.alpha=1.0f;
2273     }
2274 bottomtexture:
2275     /* bottomtexture */
2276     ceiling_height=backsector->floorheight;
2277     floor_height=frontsector->floorheight;
2278     if (frontsector->floorpic==skyflatnum)
2279     {
2280       wall.ybottom=-255.0f;
2281       if (
2282           (backsector->ceilingheight==backsector->floorheight) &&
2283           (backsector->floorpic==skyflatnum)
2284          )
2285       {
2286         wall.ytop=(float)backsector->floorheight/MAP_SCALE;
2287         SKYTEXTURE(frontsector->sky,backsector->sky);
2288         ADDWALL(&wall);
2289       }
2290       else
2291       {
2292         if ( (texturetranslation[seg->sidedef->bottomtexture]!=NO_TEXTURE) )
2293         {
2294           wall.ytop=(float)frontsector->floorheight/MAP_SCALE;
2295           SKYTEXTURE(frontsector->sky,backsector->sky);
2296           ADDWALL(&wall);
2297         }
2298         else
2299           if ( (backsector->floorheight >= frontsector->ceilingheight) ||
2300                (backsector->floorpic != skyflatnum) )
2301           {
2302             wall.ytop=(float)backsector->floorheight/MAP_SCALE;
2303             SKYTEXTURE(frontsector->sky,backsector->sky);
2304             ADDWALL(&wall);
2305           }
2306       }
2307     }
2308     if (floor_height<ceiling_height)
2309     {
2310       temptex=gld_RegisterTexture(texturetranslation[seg->sidedef->bottomtexture], true, false);
2311       if (temptex)
2312       {
2313         wall.gltexture=temptex;
2314         CALC_Y_VALUES(wall, lineheight, floor_height, ceiling_height);
2315         CALC_TEX_VALUES_BOTTOM(
2316           wall, seg, (LINE->flags & ML_DONTPEGBOTTOM)>0,
2317           segs[seg->iSegID].length, lineheight,
2318           floor_height-frontsector->ceilingheight
2319         );
2320         ADDWALL(&wall);
2321       }
2322     }
2323   }
2324 }
2325 
2326 #undef LINE
2327 #undef CALC_Y_VALUES
2328 #undef OU
2329 #undef OV
2330 #undef OV_PEG
2331 #undef CALC_TEX_VALUES_TOP
2332 #undef CALC_TEX_VALUES_MIDDLE1S
2333 #undef CALC_TEX_VALUES_MIDDLE2S
2334 #undef CALC_TEX_VALUES_BOTTOM
2335 #undef SKYTEXTURE
2336 #undef ADDWALL
2337 
gld_PreprocessSegs(void)2338 static void gld_PreprocessSegs(void)
2339 {
2340   int i;
2341 
2342   gl_segs=Z_Malloc(numsegs*sizeof(GLSeg),PU_LEVEL,0);
2343   for (i=0; i<numsegs; i++)
2344   {
2345     gl_segs[i].x1=-(float)segs[i].v1->x/(float)MAP_SCALE;
2346     gl_segs[i].z1= (float)segs[i].v1->y/(float)MAP_SCALE;
2347     gl_segs[i].x2=-(float)segs[i].v2->x/(float)MAP_SCALE;
2348     gl_segs[i].z2= (float)segs[i].v2->y/(float)MAP_SCALE;
2349   }
2350 }
2351 
2352 /*****************
2353  *               *
2354  * Flats         *
2355  *               *
2356  *****************/
2357 
gld_DrawFlat(GLFlat * flat)2358 static void gld_DrawFlat(GLFlat *flat)
2359 {
2360   int loopnum; // current loop number
2361   GLLoopDef *currentloop; // the current loop
2362 #ifndef USE_VERTEX_ARRAYS
2363   int vertexnum;
2364 #endif
2365 
2366   gld_BindFlat(flat->gltexture);
2367   gld_StaticLight(flat->light);
2368   glMatrixMode(GL_MODELVIEW);
2369   glPushMatrix();
2370   glTranslatef(0.0f,flat->z,0.0f);
2371   glMatrixMode(GL_TEXTURE);
2372   glPushMatrix();
2373   glTranslatef(flat->uoffs/64.0f,flat->voffs/64.0f,0.0f);
2374   if (flat->sectornum>=0)
2375   {
2376     // go through all loops of this sector
2377 #ifndef USE_VERTEX_ARRAYS
2378     for (loopnum=0; loopnum<sectorloops[flat->sectornum].loopcount; loopnum++)
2379     {
2380       // set the current loop
2381       currentloop=&sectorloops[flat->sectornum].loops[loopnum];
2382       if (!currentloop)
2383         continue;
2384       // set the mode (GL_TRIANGLES, GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN)
2385       glBegin(currentloop->mode);
2386       // go through all vertexes of this loop
2387       for (vertexnum=currentloop->vertexindex; vertexnum<(currentloop->vertexindex+currentloop->vertexcount); vertexnum++)
2388       {
2389         // set texture coordinate of this vertex
2390         glTexCoord2fv(&gld_texcoords[vertexnum*2]);
2391         // set vertex coordinate
2392         glVertex3fv(&gld_vertexes[vertexnum*3]);
2393       }
2394       // end of loop
2395       glEnd();
2396     }
2397 #else
2398     for (loopnum=0; loopnum<sectorloops[flat->sectornum].loopcount; loopnum++)
2399     {
2400       // set the current loop
2401       currentloop=&sectorloops[flat->sectornum].loops[loopnum];
2402       glDrawArrays(currentloop->mode,currentloop->vertexindex,currentloop->vertexcount);
2403     }
2404 #endif
2405   }
2406   glPopMatrix();
2407   glMatrixMode(GL_MODELVIEW);
2408   glPopMatrix();
2409 }
2410 
2411 // gld_AddFlat
2412 //
2413 // This draws on flat for the sector "num"
2414 // The ceiling boolean indicates if the flat is a floor(false) or a ceiling(true)
2415 
gld_AddFlat(int sectornum,boolean ceiling,visplane_t * plane)2416 static void gld_AddFlat(int sectornum, boolean ceiling, visplane_t *plane)
2417 {
2418   sector_t *sector; // the sector we want to draw
2419   sector_t tempsec; // needed for R_FakeFlat
2420   int floorlightlevel;      // killough 3/16/98: set floor lightlevel
2421   int ceilinglightlevel;    // killough 4/11/98
2422   GLFlat flat;
2423 
2424   if (sectornum<0)
2425     return;
2426   flat.sectornum=sectornum;
2427   sector=&sectors[sectornum]; // get the sector
2428   sector=R_FakeFlat(sector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); // for boom effects
2429   flat.ceiling=ceiling;
2430   if (!ceiling) // if it is a floor ...
2431   {
2432     if (sector->floorpic == skyflatnum) // don't draw if sky
2433       return;
2434     // get the texture. flattranslation is maintained by doom and
2435     // contains the number of the current animation frame
2436     flat.gltexture=gld_RegisterFlat(flattranslation[sector->floorpic], true);
2437     if (!flat.gltexture)
2438       return;
2439     // get the lightlevel from floorlightlevel
2440     flat.light=gld_CalcLightLevel(floorlightlevel+(extralight<<5));
2441     // calculate texture offsets
2442     flat.uoffs=(float)sector->floor_xoffs/(float)FRACUNIT;
2443     flat.voffs=(float)sector->floor_yoffs/(float)FRACUNIT;
2444   }
2445   else // if it is a ceiling ...
2446   {
2447     if (sector->ceilingpic == skyflatnum) // don't draw if sky
2448       return;
2449     // get the texture. flattranslation is maintained by doom and
2450     // contains the number of the current animation frame
2451     flat.gltexture=gld_RegisterFlat(flattranslation[sector->ceilingpic], true);
2452     if (!flat.gltexture)
2453       return;
2454     // get the lightlevel from ceilinglightlevel
2455     flat.light=gld_CalcLightLevel(ceilinglightlevel+(extralight<<5));
2456     // calculate texture offsets
2457     flat.uoffs=(float)sector->ceiling_xoffs/(float)FRACUNIT;
2458     flat.voffs=(float)sector->ceiling_yoffs/(float)FRACUNIT;
2459   }
2460 
2461   // get height from plane
2462   flat.z=(float)plane->height/MAP_SCALE;
2463 
2464   if (gld_drawinfo.num_flats>=gld_drawinfo.max_flats)
2465   {
2466     gld_drawinfo.max_flats+=128;
2467     gld_drawinfo.flats=Z_Realloc(gld_drawinfo.flats,gld_drawinfo.max_flats*sizeof(GLFlat),PU_LEVEL,0);
2468   }
2469   gld_AddDrawItem(GLDIT_FLAT, gld_drawinfo.num_flats);
2470   gld_drawinfo.flats[gld_drawinfo.num_flats++]=flat;
2471 }
2472 
gld_AddPlane(int subsectornum,visplane_t * floor,visplane_t * ceiling)2473 void gld_AddPlane(int subsectornum, visplane_t *floor, visplane_t *ceiling)
2474 {
2475   subsector_t *subsector;
2476 
2477   // check if all arrays are allocated
2478   if (!sectorrendered)
2479     return;
2480 
2481   subsector = &subsectors[subsectornum];
2482   if (!subsector)
2483     return;
2484   if (sectorrendered[subsector->sector->iSectorID]!=rendermarker) // if not already rendered
2485   {
2486     // render the floor
2487     if (floor)
2488       gld_AddFlat(subsector->sector->iSectorID, false, floor);
2489     // render the ceiling
2490     if (ceiling)
2491       gld_AddFlat(subsector->sector->iSectorID, true, ceiling);
2492     // set rendered true
2493     sectorrendered[subsector->sector->iSectorID]=rendermarker;
2494   }
2495 }
2496 
2497 /*****************
2498  *               *
2499  * Sprites       *
2500  *               *
2501  *****************/
2502 
gld_DrawSprite(GLSprite * sprite)2503 static void gld_DrawSprite(GLSprite *sprite)
2504 {
2505   gld_BindPatch(sprite->gltexture,sprite->cm);
2506   glMatrixMode(GL_MODELVIEW);
2507   glPushMatrix();
2508   // Bring items up out of floor by configurable amount times .01 Mead 8/13/03
2509   glTranslatef(sprite->x,sprite->y+ (.01f * (float)gl_sprite_offset),sprite->z);
2510   glRotatef(inv_yaw,0.0f,1.0f,0.0f);
2511   if(sprite->shadow)
2512   {
2513     glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
2514     //glColor4f(0.2f,0.2f,0.2f,(float)tran_filter_pct/100.0f);
2515     glAlphaFunc(GL_GEQUAL,0.1f);
2516     glColor4f(0.2f,0.2f,0.2f,0.33f);
2517   }
2518   else
2519   {
2520     if(sprite->trans)
2521       gld_StaticLightAlpha(sprite->light,(float)tran_filter_pct/100.0f);
2522     else
2523       gld_StaticLight(sprite->light);
2524   }
2525   glBegin(GL_TRIANGLE_STRIP);
2526     glTexCoord2f(sprite->ul, sprite->vt); glVertex3f(sprite->x1, sprite->y1, 0.0f);
2527     glTexCoord2f(sprite->ur, sprite->vt); glVertex3f(sprite->x2, sprite->y1, 0.0f);
2528     glTexCoord2f(sprite->ul, sprite->vb); glVertex3f(sprite->x1, sprite->y2, 0.0f);
2529     glTexCoord2f(sprite->ur, sprite->vb); glVertex3f(sprite->x2, sprite->y2, 0.0f);
2530   glEnd();
2531 
2532   glPopMatrix();
2533 
2534   if(sprite->shadow)
2535   {
2536     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2537     glAlphaFunc(GL_GEQUAL,0.5f);
2538   }
2539 }
2540 
gld_AddSprite(vissprite_t * vspr)2541 void gld_AddSprite(vissprite_t *vspr)
2542 {
2543   mobj_t *pSpr=vspr->thing;
2544   GLSprite sprite;
2545   float voff,hoff;
2546 
2547   sprite.scale=vspr->scale;
2548   if (pSpr->frame & FF_FULLBRIGHT)
2549     sprite.light = 1.0f;
2550   else
2551     sprite.light = gld_CalcLightLevel(pSpr->subsector->sector->lightlevel+(extralight<<5));
2552   sprite.cm=CR_LIMIT+(int)((pSpr->flags & MF_TRANSLATION) >> (MF_TRANSSHIFT));
2553   sprite.gltexture=gld_RegisterPatch(vspr->patch+firstspritelump,sprite.cm);
2554   if (!sprite.gltexture)
2555     return;
2556   sprite.shadow = (pSpr->flags & MF_SHADOW) != 0;
2557   sprite.trans  = (pSpr->flags & MF_TRANSLUCENT) != 0;
2558   if (movement_smooth)
2559   {
2560     sprite.x = (float)(-pSpr->PrevX + FixedMul (tic_vars.frac, -pSpr->x - (-pSpr->PrevX)))/MAP_SCALE;
2561     sprite.y = (float)(pSpr->PrevZ + FixedMul (tic_vars.frac, pSpr->z - pSpr->PrevZ))/MAP_SCALE;
2562     sprite.z = (float)(pSpr->PrevY + FixedMul (tic_vars.frac, pSpr->y - pSpr->PrevY))/MAP_SCALE;
2563   }
2564   else
2565   {
2566     sprite.x=-(float)pSpr->x/MAP_SCALE;
2567     sprite.y= (float)pSpr->z/MAP_SCALE;
2568     sprite.z= (float)pSpr->y/MAP_SCALE;
2569   }
2570 
2571   sprite.vt=0.0f;
2572   sprite.vb=(float)sprite.gltexture->height/(float)sprite.gltexture->tex_height;
2573   if (vspr->flip)
2574   {
2575     sprite.ul=0.0f;
2576     sprite.ur=(float)sprite.gltexture->width/(float)sprite.gltexture->tex_width;
2577   }
2578   else
2579   {
2580     sprite.ul=(float)sprite.gltexture->width/(float)sprite.gltexture->tex_width;
2581     sprite.ur=0.0f;
2582   }
2583   hoff=(float)sprite.gltexture->leftoffset/(float)(MAP_COEFF);
2584   voff=(float)sprite.gltexture->topoffset/(float)(MAP_COEFF);
2585   sprite.x1=hoff-((float)sprite.gltexture->realtexwidth/(float)(MAP_COEFF));
2586   sprite.x2=hoff;
2587   sprite.y1=voff;
2588   sprite.y2=voff-((float)sprite.gltexture->realtexheight/(float)(MAP_COEFF));
2589 
2590   if (gld_drawinfo.num_sprites>=gld_drawinfo.max_sprites)
2591   {
2592     gld_drawinfo.max_sprites+=128;
2593     gld_drawinfo.sprites=Z_Realloc(gld_drawinfo.sprites,gld_drawinfo.max_sprites*sizeof(GLSprite),PU_LEVEL,0);
2594   }
2595   gld_AddDrawItem(GLDIT_SPRITE, gld_drawinfo.num_sprites);
2596   gld_drawinfo.sprites[gld_drawinfo.num_sprites++]=sprite;
2597 }
2598 
2599 /*****************
2600  *               *
2601  * Draw          *
2602  *               *
2603  *****************/
2604 
gld_DrawScene(player_t * player)2605 void gld_DrawScene(player_t *player)
2606 {
2607   int i,j,k,count;
2608   fixed_t max_scale;
2609 
2610   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2611   glEnableClientState(GL_VERTEX_ARRAY);
2612   rendered_visplanes = rendered_segs = rendered_vissprites = 0;
2613   for (i=gld_drawinfo.num_drawitems; i>=0; i--)
2614   {
2615     switch (gld_drawinfo.drawitems[i].itemtype)
2616     {
2617     case GLDIT_FLAT:
2618       // enable backside removing
2619       glEnable(GL_CULL_FACE);
2620       // floors
2621       glCullFace(GL_FRONT);
2622       for (j=(gld_drawinfo.drawitems[i].itemcount-1); j>=0; j--)
2623         if (!gld_drawinfo.flats[j+gld_drawinfo.drawitems[i].firstitemindex].ceiling)
2624         {
2625           rendered_visplanes++;
2626           gld_DrawFlat(&gld_drawinfo.flats[j+gld_drawinfo.drawitems[i].firstitemindex]);
2627         }
2628       // ceilings
2629       glCullFace(GL_BACK);
2630       for (j=(gld_drawinfo.drawitems[i].itemcount-1); j>=0; j--)
2631         if (gld_drawinfo.flats[j+gld_drawinfo.drawitems[i].firstitemindex].ceiling)
2632         {
2633           rendered_visplanes++;
2634           gld_DrawFlat(&gld_drawinfo.flats[j+gld_drawinfo.drawitems[i].firstitemindex]);
2635         }
2636       // disable backside removing
2637       glDisable(GL_CULL_FACE);
2638       break;
2639     }
2640   }
2641   for (i=gld_drawinfo.num_drawitems; i>=0; i--)
2642   {
2643     switch (gld_drawinfo.drawitems[i].itemtype)
2644     {
2645     case GLDIT_WALL:
2646       count=0;
2647       for (k=GLDWF_TOP; k<=GLDWF_SKYFLIP; k++)
2648       {
2649         if (count>=gld_drawinfo.drawitems[i].itemcount)
2650           continue;
2651         if ( (gl_drawskys) && (k>=GLDWF_SKY) )
2652         {
2653           if (comp[comp_skymap] && gl_shared_texture_palette)
2654             glDisable(GL_SHARED_TEXTURE_PALETTE_EXT);
2655           glEnable(GL_TEXTURE_GEN_S);
2656           glEnable(GL_TEXTURE_GEN_T);
2657           glEnable(GL_TEXTURE_GEN_Q);
2658           glColor4fv(gl_whitecolor);
2659         }
2660         for (j=(gld_drawinfo.drawitems[i].itemcount-1); j>=0; j--)
2661           if (gld_drawinfo.walls[j+gld_drawinfo.drawitems[i].firstitemindex].flag==k)
2662           {
2663             rendered_segs++;
2664             count++;
2665             gld_DrawWall(&gld_drawinfo.walls[j+gld_drawinfo.drawitems[i].firstitemindex]);
2666           }
2667         if (gl_drawskys)
2668         {
2669           glDisable(GL_TEXTURE_GEN_Q);
2670           glDisable(GL_TEXTURE_GEN_T);
2671           glDisable(GL_TEXTURE_GEN_S);
2672           if (comp[comp_skymap] && gl_shared_texture_palette)
2673             glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
2674         }
2675       }
2676       break;
2677     case GLDIT_SPRITE:
2678       if (gl_sortsprites)
2679       {
2680         do
2681         {
2682           max_scale=INT_MAX;
2683           k=-1;
2684           for (j=(gld_drawinfo.drawitems[i].itemcount-1); j>=0; j--)
2685             if (gld_drawinfo.sprites[j+gld_drawinfo.drawitems[i].firstitemindex].scale<max_scale)
2686             {
2687               max_scale=gld_drawinfo.sprites[j+gld_drawinfo.drawitems[i].firstitemindex].scale;
2688               k=j+gld_drawinfo.drawitems[i].firstitemindex;
2689             }
2690           if (k>=0)
2691           {
2692             rendered_vissprites++;
2693             gld_DrawSprite(&gld_drawinfo.sprites[k]);
2694             gld_drawinfo.sprites[k].scale=INT_MAX;
2695           }
2696         } while (max_scale!=INT_MAX);
2697       }
2698       else
2699       {
2700         for (j=(gld_drawinfo.drawitems[i].itemcount-1); j>=0; j--,rendered_vissprites++)
2701           gld_DrawSprite(&gld_drawinfo.sprites[j+gld_drawinfo.drawitems[i].firstitemindex]);
2702       }
2703       break;
2704     }
2705   }
2706   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2707   glDisableClientState(GL_VERTEX_ARRAY);
2708 }
2709 
gld_PreprocessLevel(void)2710 void gld_PreprocessLevel(void)
2711 {
2712   if (precache)
2713     gld_Precache();
2714   gld_PreprocessSectors();
2715   gld_PreprocessSegs();
2716   memset(&gld_drawinfo,0,sizeof(GLDrawInfo));
2717   glTexCoordPointer(2,GL_FLOAT,0,gld_texcoords);
2718   glVertexPointer(3,GL_FLOAT,0,gld_vertexes);
2719 }
2720