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==§ors[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==§ors[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==§ors[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==§ors[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==§ors[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==§ors[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=§orloops[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=§orloops[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=§ors[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