File: wl_cloudsky.cpp

package info (click to toggle)
wolf4sdl 1.7+svn262+dfsg1-5
  • links: PTS, VCS
  • area: contrib
  • in suites: bullseye, buster, sid
  • size: 4,112 kB
  • sloc: cpp: 34,696; ansic: 1,257; objc: 246; makefile: 159; sh: 44
file content (259 lines) | stat: -rw-r--r-- 8,725 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#include "version.h"

#ifdef USE_CLOUDSKY

#include "wl_def.h"
#include "wl_cloudsky.h"

// Each colormap defines a number of colors which should be mapped from
// the skytable. The according colormapentry_t array defines how these colors should
// be mapped to the wolfenstein palette. The first int of each entry defines
// how many colors are grouped to this entry and the absolute value of the
// second int sets the starting palette index for this pair. If this value is
// negative the index will be decremented for every color, if it's positive
// it will be incremented.
//
// Example colormap:
//   colormapentry_t colmapents_1[] = { { 6, -10 }, { 2, 40 } };
//   colormap_t colorMaps[] = {
//      { 8, colmapents_1 }
//   };
//
//   The colormap 0 consists of 8 colors. The first color group consists of 6
//   colors and starts descending at palette index 10: 10, 9, 8, 7, 6, 5
//   The second color group consists of 2 colors and starts ascending at
//   index 40: 40, 41
//   There's no other color group because all colors of this colormap are
//   already used (6+2=8)
//
// Warning: Always make sure that the sum of the amount of the colors in all
//          color groups is the number of colors used for your colormap!

colormapentry_t colmapents_1[] = { { 16, -31 }, { 16, 136 } };
colormapentry_t colmapents_2[] = { { 16, -31 } };

colormap_t colorMaps[] = {
    { 32, colmapents_1 },
    { 16, colmapents_2 }
};

const int numColorMaps = lengthof(colorMaps);

// The sky definitions which can be selected as defined by GetCloudSkyDefID() in wl_def.h
// You can use <TAB>+Z in debug mode to find out suitable values for seed and colorMapIndex
// Each entry consists of seed, speed, angle and colorMapIndex
cloudsky_t cloudSkys[] = {
    { 626,   800,  20,  0 },
    { 1234,  650,  60,  1 },
    { 0,     700,  120, 0 },
    { 0,     0,    0,   0 },
    { 11243, 750,  310, 0 },
    { 32141, 750,  87,  0 },
    { 12124, 750,  64,  0 },
    { 55543, 500,  240, 0 },
    { 65535, 200,  54,  1 },
    { 4,     1200, 290, 0 },
};

byte skyc[65536L];

long cloudx = 0, cloudy = 0;
cloudsky_t *curSky = NULL;

#ifdef USE_FEATUREFLAGS

// The lower left tile of every map determines the used cloud sky definition from cloudSkys.
static int GetCloudSkyDefID()
{
    int skyID = ffDataBottomLeft;
    assert(skyID >= 0 && skyID < lengthof(cloudSkys));
    return skyID;
}

#else

static int GetCloudSkyDefID()
{
    int skyID;
    switch(gamestate.episode * 10 + mapon)
    {
        case  0: skyID =  0; break;
        case  1: skyID =  1; break;
        case  2: skyID =  2; break;
        case  3: skyID =  3; break;
        case  4: skyID =  4; break;
        case  5: skyID =  5; break;
        case  6: skyID =  6; break;
        case  7: skyID =  7; break;
        case  8: skyID =  8; break;
        case  9: skyID =  9; break;
        default: skyID =  9; break;
    }
    assert(skyID >= 0 && skyID < lengthof(cloudSkys));
    return skyID;
}

#endif

void SplitS(unsigned size,unsigned x1,unsigned y1,unsigned x2,unsigned y2)
{
   if(size==1) return;
   if(!skyc[((x1+size/2)*256+y1)])
   {
      skyc[((x1+size/2)*256+y1)]=(byte)(((int)skyc[(x1*256+y1)]
            +(int)skyc[((x2&0xff)*256+y1)])/2)+rand()%(size*2)-size;
      if(!skyc[((x1+size/2)*256+y1)]) skyc[((x1+size/2)*256+y1)]=1;
   }
   if(!skyc[((x1+size/2)*256+(y2&0xff))])
   {
      skyc[((x1+size/2)*256+(y2&0xff))]=(byte)(((int)skyc[(x1*256+(y2&0xff))]
            +(int)skyc[((x2&0xff)*256+(y2&0xff))])/2)+rand()%(size*2)-size;
      if(!skyc[((x1+size/2)*256+(y2&0xff))])
         skyc[((x1+size/2)*256+(y2&0xff))]=1;
   }
   if(!skyc[(x1*256+y1+size/2)])
   {
      skyc[(x1*256+y1+size/2)]=(byte)(((int)skyc[(x1*256+y1)]
            +(int)skyc[(x1*256+(y2&0xff))])/2)+rand()%(size*2)-size;
      if(!skyc[(x1*256+y1+size/2)]) skyc[(x1*256+y1+size/2)]=1;
   }
   if(!skyc[((x2&0xff)*256+y1+size/2)])
   {
      skyc[((x2&0xff)*256+y1+size/2)]=(byte)(((int)skyc[((x2&0xff)*256+y1)]
            +(int)skyc[((x2&0xff)*256+(y2&0xff))])/2)+rand()%(size*2)-size;
      if(!skyc[((x2&0xff)*256+y1+size/2)]) skyc[((x2&0xff)*256+y1+size/2)]=1;
   }

   skyc[((x1+size/2)*256+y1+size/2)]=(byte)(((int)skyc[(x1*256+y1)]
         +(int)skyc[((x2&0xff)*256+y1)]+(int)skyc[(x1*256+(y2&0xff))]
         +(int)skyc[((x2&0xff)*256+(y2&0xff))])/4)+rand()%(size*2)-size;

   SplitS(size/2,x1,y1+size/2,x1+size/2,y2);
   SplitS(size/2,x1+size/2,y1,x2,y1+size/2);
   SplitS(size/2,x1+size/2,y1+size/2,x2,y2);
   SplitS(size/2,x1,y1,x1+size/2,y1+size/2);
}

void InitSky()
{
    unsigned cloudskyid = GetCloudSkyDefID();
    if(cloudskyid >= lengthof(cloudSkys))
        Quit("Illegal cloud sky id: %u", cloudskyid);
    curSky = &cloudSkys[cloudskyid];

    memset(skyc, 0, sizeof(skyc));
    // funny water texture if used instead of memset ;D
    // for(int i = 0; i < 65536; i++)
    //     skyc[i] = rand() % 32 * 8;

    srand(curSky->seed);
    skyc[0] = rand() % 256;
    SplitS(256, 0, 0, 256, 256);

    // Smooth the clouds a bit
    for(int k = 0; k < 2; k++)
    {
        for(int i = 0; i < 256; i++)
        {
            for(int j = 0; j < 256; j++)
            {
                int32_t val = -skyc[j * 256 + i];
                for(int m = 0; m < 3; m++)
                {
                    for(int n = 0; n < 3; n++)
                    {
                        val += skyc[((j + n - 1) & 0xff) * 256 + ((i + m - 1) & 0xff)];
                    }
                }
                skyc[j * 256 + i] = (byte)(val >> 3);
            }
        }
    }

    // the following commented line could be useful, if you're trying to
    // create a new color map. This will display your current color map
    // in one (of course repeating) stripe of the sky

    // for(int i = 0; i < 256; i++)
    //     skyc[i] = skyc[i + 256] = skyc[i + 512] = i;

    if(curSky->colorMapIndex >= lengthof(colorMaps))
        Quit("Illegal colorMapIndex for cloud sky def %u: %u", cloudskyid, curSky->colorMapIndex);

    colormap_t *curMap = &colorMaps[curSky->colorMapIndex];
    int numColors = curMap->numColors;
    byte colormap[256];
    colormapentry_t *curEntry = curMap->entries;
    for(int calcedCols = 0; calcedCols < numColors; curEntry++)
    {
        if(curEntry->startAndDir < 0)
        {
            for(int i = 0, ind = -curEntry->startAndDir; i < curEntry->length; i++, ind--)
                colormap[calcedCols++] = ind;
        }
        else
        {
            for(int i = 0, ind = curEntry->startAndDir; i < curEntry->length; i++, ind++)
                colormap[calcedCols++] = ind;
        }
    }

    for(int i = 0; i < 256; i++)
    {
        for(int j = 0; j < 256; j++)
        {
            skyc[i * 256 + j] = colormap[skyc[i * 256 + j] * numColors / 256];
        }
    }
}

// Based on Textured Floor and Ceiling by DarkOne
void DrawClouds(byte *vbuf, unsigned vbufPitch, int min_wallheight)
{
    // Move clouds
    fixed moveDist = tics * curSky->speed;
    cloudx += FixedMul(moveDist,sintable[curSky->angle]);
    cloudy -= FixedMul(moveDist,costable[curSky->angle]);

    // Draw them
    int y0, halfheight;
    unsigned top_offset0;
    fixed dist;                                // distance to row projection
    fixed tex_step;                            // global step per one screen pixel
    fixed gu, gv, du, dv;                      // global texture coordinates
    int u, v;                                  // local texture coordinates

    // ------ * prepare * --------
    halfheight = viewheight >> 1;
    y0 = min_wallheight >> 3;                  // starting y value
    if(y0 > halfheight)
        return;                                // view obscured by walls
    if(!y0) y0 = 1;                            // don't let division by zero
    top_offset0 = vbufPitch * (halfheight - y0 - 1);

    // draw horizontal lines
    for(int y = y0, top_offset = top_offset0; y < halfheight; y++, top_offset -= vbufPitch)
    {
        dist = (heightnumerator / y) << 8;
        gu =  viewx + FixedMul(dist, viewcos) + cloudx;
        gv = -viewy + FixedMul(dist, viewsin) + cloudy;
        tex_step = (dist << 8) / viewwidth / 175;
        du =  FixedMul(tex_step, viewsin);
        dv = -FixedMul(tex_step, viewcos);
        gu -= (viewwidth >> 1)*du;
        gv -= (viewwidth >> 1)*dv;          // starting point (leftmost)
        for(int x = 0, top_add = top_offset; x < viewwidth; x++, top_add++)
        {
            if(wallheight[x] >> 3 <= y)
            {
                u = (gu >> 13) & 255;
                v = (gv >> 13) & 255;
                vbuf[top_add] = skyc[((255 - u) << 8) + 255 - v];
            }
            gu += du;
            gv += dv;
        }
    }
}

#endif