]> icculus.org git repositories - theoddone33/hheretic.git/blob - opengl/ogl_sky.c
More 64bit fixes
[theoddone33/hheretic.git] / opengl / ogl_sky.c
1
2 //**************************************************************************
3 //**
4 //** OGL_SKY.C
5 //**
6 //**************************************************************************
7
8 // HEADER FILES ------------------------------------------------------------
9
10 #include <GL/gl.h>
11 #include "doomdef.h"
12 #include "r_local.h"
13 #include "ogl_def.h"
14 #include "ogl_rl.h"
15 #include <math.h>
16
17 // MACROS ------------------------------------------------------------------
18
19 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
20
21 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
22
23 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
24
25 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
26
27 extern float            texw, texh;
28
29 extern float            vx, vy, vz;
30
31 extern byte                     topLineRGB[3];
32 int                     skyDetail = 1;
33
34 // PUBLIC DATA DEFINITIONS -------------------------------------------------
35
36 int                     skyhemispheres;
37 fadeout_t       fadeOut[2];             // For both skies.
38
39 // PRIVATE DATA DEFINITIONS ------------------------------------------------
40
41 // CODE --------------------------------------------------------------------
42
43 // The texture offset to be applied to the texture coordinates in SkyVertex().
44 static float            maxSideAngle = (float) PI/3;
45 static float            texoff;
46 static int                      rows, columns;  
47 static float            scale = 32;     // Fogging affects, thus close-by.
48 static boolean          yflip;
49 static fadeout_t        *currentFO;
50
51 // Calculate the vertex and texture coordinates.
52 static void SkyVertex(int r, int c)
53 {
54         // The direction must be clockwise.
55         float topAngle = c/(float)columns * 2*PI;
56         float sideAngle = maxSideAngle * (rows-r)/(float)rows;
57         float height = sin(sideAngle);
58         float realRadius = scale*cos(sideAngle);
59         float x = vx + realRadius*cos(topAngle), 
60                         z = vz + realRadius*sin(topAngle),
61                         y = vy + ((!yflip)? scale*height : -scale*height);      
62
63         // And the texture coordinates.
64         if(!yflip)      // Flipped Y is for the lower hemisphere.
65                 glTexCoord2f(4*c/(float)columns + texoff/texw, r/(float)rows*200.0/256.0);
66         else
67                 glTexCoord2f(4*c/(float)columns + texoff/texw, (rows-r)/(float)rows*200.0/256.0);
68         // Also the color.
69         if(currentFO->use)
70         {
71                 if(r==0) glColor4f(1,1,1,0); else glColor3f(1,1,1);
72         }
73         else
74         {
75                 if(r==0) glColor3f(0,0,0); else glColor3f(1,1,1);
76         }
77         // And finally the vertex.
78         glVertex3f(x, y, z);    
79 }
80
81 static void CapSideVertex(int r, int c)
82 {
83         // The direction must be clockwise.
84         float topAngle = c/(float)columns * 2*PI;
85         float sideAngle = maxSideAngle * (rows-r)/(float)rows;
86         float height = sin(sideAngle);
87         float realRadius = scale*cos(sideAngle);
88
89         glVertex3f(vx + realRadius*cos(topAngle),
90                 vy + ((!yflip)? scale*height : -scale*height), 
91                 vz + realRadius*sin(topAngle)); 
92 }
93
94 // Hemi is Upper or Lower. Zero is not acceptable.
95 // The current texture is used. SKYHEMI_NO_TOPCAP can be used.
96 void OGL_RenderSkyHemisphere(int hemi)
97 {
98         int             r, c;
99
100         if(hemi & SKYHEMI_LOWER) yflip = true; else yflip = false;
101
102         // The top row (row 0) is the one that's faded out.
103         // There must be at least 4 columns. The preferable number
104         // is 4n, where n is 1, 2, 3... There should be at least
105         // two rows because the first one is always faded.
106         rows = 3;
107         columns = 4*skyDetail;  // 4n
108         if(hemi & SKYHEMI_JUST_CAP)
109         {
110                 //glBindTexture(GL_TEXTURE_2D, 0);
111                 glDisable( GL_TEXTURE_2D );
112
113                 // Use the appropriate color.
114                 if(currentFO->use)
115                         glColor3fv(currentFO->rgb);
116                 else
117                         glColor3f(0,0,0);
118                 glBegin(GL_TRIANGLE_FAN);
119                 for(c=0; c<columns; c++) CapSideVertex(0, c);
120                 glEnd();
121
122                 // If we are doing a colored fadeout...
123                 if(currentFO->use)
124                 {
125                         // We must fill the background for the top row since it'll
126                         // be partially translucent.
127                         glBegin(GL_TRIANGLE_STRIP);
128                         CapSideVertex(0, 0);
129                         for(c=0; c<columns; c++)
130                         {
131                                 CapSideVertex(1, c);    // One step down.
132                                 CapSideVertex(0, c+1);  // And one step right.
133                         }
134                         CapSideVertex(1, c);
135                         glEnd();
136                 }
137
138                 glEnable( GL_TEXTURE_2D );
139                 return;
140         }
141
142         // The total number of triangles per hemisphere can be calculated
143         // as follows: rows * columns * 2 + 2 (for the top cap).
144         for(r=0; r<rows; r++)
145         {
146                 glBegin(GL_TRIANGLE_STRIP);
147                 // Add the start vertex.
148                 SkyVertex(r, 0);
149                 for(c=0; c<columns; c++)
150                 {
151                         SkyVertex(r+1, c);      // One step down.
152                         SkyVertex(r, c+1);      // And one step right.
153                 }
154                 // Add the end vertex for this row. This vertex is also
155                 // the start vertex for the next row.
156                 SkyVertex(r+1, c);
157                 glEnd();
158                 /*glBegin(GL_QUADS);
159                 for(c=0; c<columns; c++)
160                 {
161                         SkyVertex(r, c);
162                         SkyVertex(r+1, c);
163                         SkyVertex(r+1, c+1);
164                         SkyVertex(r, c+1);
165                 }
166                 glEnd();*/
167         }
168 }
169
170 void OGL_HandleColoredFadeOut(int skynum)
171 {
172         int                     i;
173
174         currentFO = fadeOut + skynum-1;
175         // We have to remember the top line average RGB.
176         if(!currentFO->set)
177         {
178                 currentFO->set = 1;     // Now it is.
179                 for(i=0; i<3; i++) currentFO->rgb[i] = topLineRGB[i]/255.0;
180                 // Determine if it should be used.
181                 for(currentFO->use=false, i=0; i<3; i++)
182                         if(currentFO->rgb[i] > .3)
183                         {
184                                 // Colored fadeout is needed.
185                                 currentFO->use = true;
186                                 break;
187                         }
188         }
189 }
190
191 static void OGL_DrawSkyhemi(int whichHemi)
192 {
193         GLuint skyname;
194
195         skyname = OGL_PrepareSky(skytexture, false);
196
197         OGL_HandleColoredFadeOut(1);
198
199         // First the top cap.
200         OGL_RenderSkyHemisphere(whichHemi | SKYHEMI_JUST_CAP);
201         glBindTexture(GL_TEXTURE_2D, skyname);
202
203         // Render the front sky (sky1).
204         OGL_RenderSkyHemisphere(whichHemi);
205 }
206
207 void R_RenderSkyHemispheres(int hemis)
208 {
209         // IS there a sky to be rendered?
210         if(!hemis) return;
211
212         // We don't want anything written in the depth buffer, not yet.
213         glDepthMask(GL_FALSE);
214         glPushAttrib(GL_ENABLE_BIT);
215         // Disable culling, all triangles face the viewer.
216         glDisable(GL_CULL_FACE);
217         glDisable(GL_FOG);
218         // Draw the possibly visible hemispheres.
219         if(hemis & SKYHEMI_UPPER) OGL_DrawSkyhemi(SKYHEMI_UPPER);
220         if(hemis & SKYHEMI_LOWER) OGL_DrawSkyhemi(SKYHEMI_LOWER);
221         // Enable the disabled things.
222         glPopAttrib();
223         glDepthMask(GL_TRUE);
224 }