Cube  Diff

Differences From Artifact [d2b3870e35]:

To Artifact [53768c91a1]:


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
260
261


262
263
264
265
266
267


268

269

270
271
272



273
274
275
276
277
278













279

280

281

282

283
284
285
286
287
288





289
290
291


292
293
294
295
296
297
298
299
300
301
302
303











304
305

306
307
308
309



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326



















327
328

329

330
331
332
333



334
335
336
337
338




339
340

341
342
343
344
345
346









347
348

349

350

351
352
353
354
355
356






357
358
359

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
260
261


262
263
264

265



266
267
268
269
270


271
272



273
274
275
276
277


278
279
280
281
282

283
284
285
286



287
288
289
290
291
292
293






294
295
296
297
298
299
300

301





302
303
304
305


306






307
308
309
310
311
312


313
314
315
316
317
318
319

320
321
322
323

324
325


326
327
328
329
330




331
332
333
334
335
336
337
338
339
340
341
342
343
344
345

346
347
348

349
350





351
352
353
354
355
356


357
358
359











360
361
362
363
364
365
366
367
368
369
370


371




372
373
374

















375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396

397
398



399
400
401





402
403
404
405


406






407
408
409
410
411
412
413
414
415
416
417
418

419
420
421






422
423
424
425
426
427
428


-
+
+







+
-
+

-
-
-
+
+
+


+
-
+

-
-
-
-
+
+
+
+
+


-
-
-
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
-
+
+




-
-
+
+



+
+
+
-
-
+
+
+
+
+
+
+
+



+
+
+
-
-
+
+
+
+
+
+
+
+
+


-
+

+
-
+
+

-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
+
+

-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
+
+
-
-
+
-
-
-
-
+
+
+

-
-
+
+


+
-
+
+
+

-
-
+
+
+
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
+
+

-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+

-
+
-
-
-
+
+
+
-
-
+
-
-
-
-
+
+
+
+

-
-
+
+


+
-
+
+

-
-
+
+

-
-
-
-
+
+
+
+

-
-
-
-
+
+
+
+

-
-
-
+
+
+

-
-
-
-
-
+
+
+
+
+


+
-
-
+
+

-
+
-
-
-
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
+
+
-
-
+
+
+

+
-
+
+
+

-
-
-
+
+
+
+
+
+

-
-
-
-
-
-
+
+
+
+
+
+

-
+
-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+

-
-
+
+





-
+
+

+
-
+

-
-
+
+
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

+
-
+

+
-
+

-
-
-
-
-
+
+
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


+
-
+

-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+


+
-
+

+
-
-
-
-
-
-
+
+
+
+
+
+

-
-
// rendercubes.cpp: sits in between worldrender.cpp and rendergl.cpp and fills the vertex array for different cube surfaces.
// rendercubes.cpp: sits in between worldrender.cpp and rendergl.cpp and fills
// the vertex array for different cube surfaces.

#include "cube.h"

vertex *verts = NULL;
int curvert;
int curmaxverts = 10000;

void
void setarraypointers()
setarraypointers()
{
    glVertexPointer(3, GL_FLOAT, sizeof(vertex), &verts[0].x);
    glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), &verts[0].r);
    glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), &verts[0].u);
	glVertexPointer(3, GL_FLOAT, sizeof(vertex), &verts[0].x);
	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vertex), &verts[0].r);
	glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), &verts[0].u);
};

void
void reallocv()
reallocv()
{
    verts = (vertex *)realloc(verts, (curmaxverts *= 2)*sizeof(vertex));
    curmaxverts -= 10;
    if(!verts) fatal("no vertex memory!");
    setarraypointers();
	verts = (vertex *)realloc(verts, (curmaxverts *= 2) * sizeof(vertex));
	curmaxverts -= 10;
	if (!verts)
		fatal("no vertex memory!");
	setarraypointers();
};

// generating the actual vertices is done dynamically every frame and sits at the
// leaves of all these functions, and are part of the cpu bottleneck on really slow
// machines, hence the macros.
// generating the actual vertices is done dynamically every frame and sits at
// the leaves of all these functions, and are part of the cpu bottleneck on
// really slow machines, hence the macros.

#define vertcheck() { if(curvert>=curmaxverts) reallocv(); }

#define vertf(v1, v2, v3, ls, t1, t2) { vertex &v = verts[curvert++]; \
    v.u = t1; v.v = t2; \
    v.x = v1; v.y = v2; v.z = v3; \
    v.r = ls->r; v.g = ls->g; v.b = ls->b; v.a = 255; };
#define vertcheck()                                                            \
	{                                                                      \
		if (curvert >= curmaxverts)                                    \
			reallocv();                                            \
	}

#define vertf(v1, v2, v3, ls, t1, t2)                                          \
	{                                                                      \
		vertex &v = verts[curvert++];                                  \
		v.u = t1;                                                      \
		v.v = t2;                                                      \
		v.x = v1;                                                      \
		v.y = v2;                                                      \
		v.z = v3;                                                      \
		v.r = ls->r;                                                   \
		v.g = ls->g;                                                   \
		v.b = ls->b;                                                   \
		v.a = 255;                                                     \
	};

#define vert(v1, v2, v3, ls, t1, t2)                                           \
	{                                                                      \
#define vert(v1, v2, v3, ls, t1, t2) { vertf((float)(v1), (float)(v2), (float)(v3), ls, t1, t2); }
		vertf((float)(v1), (float)(v2), (float)(v3), ls, t1, t2);      \
	}

int nquads;
const float TEXTURESCALE = 32.0f;
bool floorstrip = false, deltastrip = false;
int oh, oy, ox, ogltex;                         // the o* vars are used by the stripification
int ol3r, ol3g, ol3b, ol4r, ol4g, ol4b;      
int oh, oy, ox, ogltex; // the o* vars are used by the stripification
int ol3r, ol3g, ol3b, ol4r, ol4g, ol4b;
int firstindex;
bool showm = false;

void
showmip()
{
void showmip() { showm = !showm; };
void mipstats(int a, int b, int c) { if(showm) conoutf("1x1/2x2/4x4: %d / %d / %d", a, b, c); };
	showm = !showm;
};
void
mipstats(int a, int b, int c)
{
	if (showm)
		conoutf("1x1/2x2/4x4: %d / %d / %d", a, b, c);
};

COMMAND(showmip, ARG_NONE);

#define stripend()                                                             \
	{                                                                      \
		if (floorstrip || deltastrip) {                                \
#define stripend() { if(floorstrip || deltastrip) { addstrip(ogltex, firstindex, curvert-firstindex); floorstrip = deltastrip = false; }; };
void finishstrips() { stripend(); };
			addstrip(ogltex, firstindex, curvert - firstindex);    \
			floorstrip = deltastrip = false;                       \
		};                                                             \
	};
void
finishstrips()
{
	stripend();
};

sqr sbright, sdark;
VAR(lighterror,1,8,100);
VAR(lighterror, 1, 8, 100);

void
void render_flat(int wtex, int x, int y, int size, int h, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil)  // floor/ceil quads
render_flat(int wtex, int x, int y, int size, int h, sqr *l1, sqr *l2, sqr *l3,
    sqr *l4, bool isceil) // floor/ceil quads
{
    vertcheck();
    if(showm) { l3 = l1 = &sbright; l4 = l2 = &sdark; };
	vertcheck();
	if (showm) {
		l3 = l1 = &sbright;
		l4 = l2 = &sdark;
	};

    int sx, sy;
    int gltex = lookuptexture(wtex, sx, sy);
    float xf = TEXTURESCALE/sx;
    float yf = TEXTURESCALE/sy;
    float xs = size*xf;
    float ys = size*yf;
    float xo = xf*x;
    float yo = yf*y;
	int sx, sy;
	int gltex = lookuptexture(wtex, sx, sy);
	float xf = TEXTURESCALE / sx;
	float yf = TEXTURESCALE / sy;
	float xs = size * xf;
	float ys = size * yf;
	float xo = xf * x;
	float yo = yf * y;

    bool first = !floorstrip || y!=oy+size || ogltex!=gltex || h!=oh || x!=ox;
	bool first = !floorstrip || y != oy + size || ogltex != gltex ||
	             h != oh || x != ox;

    if(first)       // start strip here
    {
        stripend();
        firstindex = curvert;
        ogltex = gltex;
        oh = h;
        ox = x;
        floorstrip = true;
        if(isceil)
	if (first) // start strip here
	{
		stripend();
		firstindex = curvert;
		ogltex = gltex;
		oh = h;
		ox = x;
		floorstrip = true;
		if (isceil) {
        {
            vert(x+size, h, y, l2, xo+xs, yo);
            vert(x,      h, y, l1, xo, yo);
			vert(x + size, h, y, l2, xo + xs, yo);
			vert(x, h, y, l1, xo, yo);
        }
        else
		} else {
        {
            vert(x,      h, y, l1, xo,    yo);
            vert(x+size, h, y, l2, xo+xs, yo);
        };
        ol3r = l1->r;
        ol3g = l1->g;
        ol3b = l1->b;
        ol4r = l2->r;
        ol4g = l2->g;
        ol4b = l2->b;
			vert(x, h, y, l1, xo, yo);
			vert(x + size, h, y, l2, xo + xs, yo);
		};
		ol3r = l1->r;
		ol3g = l1->g;
		ol3b = l1->b;
		ol4r = l2->r;
		ol4g = l2->g;
		ol4b = l2->b;
    }
    else        // continue strip
    {
        int lighterr = lighterror*2;
        if((abs(ol3r-l3->r)<lighterr && abs(ol4r-l4->r)<lighterr        // skip vertices if light values are close enough
        &&  abs(ol3g-l3->g)<lighterr && abs(ol4g-l4->g)<lighterr
        &&  abs(ol3b-l3->b)<lighterr && abs(ol4b-l4->b)<lighterr) || !wtex)   
	} else // continue strip
	{
		int lighterr = lighterror * 2;
		if ((abs(ol3r - l3->r) < lighterr &&
		        abs(ol4r - l4->r) < lighterr // skip vertices if light
		                                     // values are close enough
		        && abs(ol3g - l3->g) < lighterr &&
		        abs(ol4g - l4->g) < lighterr &&
		        abs(ol3b - l3->b) < lighterr &&
		        abs(ol4b - l4->b) < lighterr) ||
        {
            curvert -= 2;
            nquads--;
		    !wtex) {
			curvert -= 2;
			nquads--;
        }
        else
		} else {
        {
            uchar *p3 = (uchar *)(&verts[curvert-1].r);
            ol3r = p3[0];  
            ol3g = p3[1];  
            ol3b = p3[2];
            uchar *p4 = (uchar *)(&verts[curvert-2].r);  
            ol4r = p4[0];
            ol4g = p4[1];
            ol4b = p4[2];
        };
    };
			uchar *p3 = (uchar *)(&verts[curvert - 1].r);
			ol3r = p3[0];
			ol3g = p3[1];
			ol3b = p3[2];
			uchar *p4 = (uchar *)(&verts[curvert - 2].r);
			ol4r = p4[0];
			ol4g = p4[1];
			ol4b = p4[2];
		};
	};

    if(isceil)
	if (isceil) {
    {
        vert(x+size, h, y+size, l3, xo+xs, yo+ys);
        vert(x,      h, y+size, l4, xo,    yo+ys); 
		vert(x + size, h, y + size, l3, xo + xs, yo + ys);
		vert(x, h, y + size, l4, xo, yo + ys);
    }
    else
	} else {
    {
        vert(x,      h, y+size, l4, xo,    yo+ys);
        vert(x+size, h, y+size, l3, xo+xs, yo+ys); 
    };
		vert(x, h, y + size, l4, xo, yo + ys);
		vert(x + size, h, y + size, l3, xo + xs, yo + ys);
	};

    oy = y;
    nquads++;
	oy = y;
	nquads++;
};

void
void render_flatdelta(int wtex, int x, int y, int size, float h1, float h2, float h3, float h4, sqr *l1, sqr *l2, sqr *l3, sqr *l4, bool isceil)  // floor/ceil quads on a slope
render_flatdelta(int wtex, int x, int y, int size, float h1, float h2, float h3,
    float h4, sqr *l1, sqr *l2, sqr *l3, sqr *l4,
    bool isceil) // floor/ceil quads on a slope
{
    vertcheck();
    if(showm) { l3 = l1 = &sbright; l4 = l2 = &sdark; };
	vertcheck();
	if (showm) {
		l3 = l1 = &sbright;
		l4 = l2 = &sdark;
	};

    int sx, sy;
    int gltex = lookuptexture(wtex, sx, sy);
    float xf = TEXTURESCALE/sx;
    float yf = TEXTURESCALE/sy;
    float xs = size*xf;
    float ys = size*yf;
    float xo = xf*x;
    float yo = yf*y;
	int sx, sy;
	int gltex = lookuptexture(wtex, sx, sy);
	float xf = TEXTURESCALE / sx;
	float yf = TEXTURESCALE / sy;
	float xs = size * xf;
	float ys = size * yf;
	float xo = xf * x;
	float yo = yf * y;

    bool first = !deltastrip || y!=oy+size || ogltex!=gltex || x!=ox; 
	bool first =
	    !deltastrip || y != oy + size || ogltex != gltex || x != ox;

    if(first) 
	if (first) {
    {
        stripend();
        firstindex = curvert;
        ogltex = gltex;
        ox = x;
        deltastrip = true;
        if(isceil)
		stripend();
		firstindex = curvert;
		ogltex = gltex;
		ox = x;
		deltastrip = true;
		if (isceil) {
        {
            vertf((float)x+size, h2, (float)y,      l2, xo+xs, yo);
            vertf((float)x,      h1, (float)y,      l1, xo,    yo);
			vertf((float)x + size, h2, (float)y, l2, xo + xs, yo);
			vertf((float)x, h1, (float)y, l1, xo, yo);
        }
        else
		} else {
        {
            vertf((float)x,      h1, (float)y,      l1, xo,    yo);
            vertf((float)x+size, h2, (float)y,      l2, xo+xs, yo);
        };
        ol3r = l1->r;
        ol3g = l1->g;
        ol3b = l1->b;
        ol4r = l2->r;
        ol4g = l2->g;
        ol4b = l2->b;
    };
			vertf((float)x, h1, (float)y, l1, xo, yo);
			vertf((float)x + size, h2, (float)y, l2, xo + xs, yo);
		};
		ol3r = l1->r;
		ol3g = l1->g;
		ol3b = l1->b;
		ol4r = l2->r;
		ol4g = l2->g;
		ol4b = l2->b;
	};

    if(isceil)
	if (isceil) {
    {
        vertf((float)x+size, h3, (float)y+size, l3, xo+xs, yo+ys); 
        vertf((float)x,      h4, (float)y+size, l4, xo,    yo+ys);
		vertf(
		    (float)x + size, h3, (float)y + size, l3, xo + xs, yo + ys);
		vertf((float)x, h4, (float)y + size, l4, xo, yo + ys);
    }
    else
	} else {
    {
        vertf((float)x,      h4, (float)y+size, l4, xo,    yo+ys);
        vertf((float)x+size, h3, (float)y+size, l3, xo+xs, yo+ys); 
    };
		vertf((float)x, h4, (float)y + size, l4, xo, yo + ys);
		vertf(
		    (float)x + size, h3, (float)y + size, l3, xo + xs, yo + ys);
	};

    oy = y;
    nquads++;
	oy = y;
	nquads++;
};

void
void render_2tris(sqr *h, sqr *s, int x1, int y1, int x2, int y2, int x3, int y3, sqr *l1, sqr *l2, sqr *l3)   // floor/ceil tris on a corner cube
render_2tris(sqr *h, sqr *s, int x1, int y1, int x2, int y2, int x3, int y3,
    sqr *l1, sqr *l2, sqr *l3) // floor/ceil tris on a corner cube
{
    stripend();
    vertcheck();
	stripend();
	vertcheck();

    int sx, sy;
    int gltex = lookuptexture(h->ftex, sx, sy);
    float xf = TEXTURESCALE/sx;
    float yf = TEXTURESCALE/sy;
	int sx, sy;
	int gltex = lookuptexture(h->ftex, sx, sy);
	float xf = TEXTURESCALE / sx;
	float yf = TEXTURESCALE / sy;

    vertf((float)x1, h->floor, (float)y1, l1, xf*x1, yf*y1);
    vertf((float)x2, h->floor, (float)y2, l2, xf*x2, yf*y2);
    vertf((float)x3, h->floor, (float)y3, l3, xf*x3, yf*y3);
    addstrip(gltex, curvert-3, 3);
	vertf((float)x1, h->floor, (float)y1, l1, xf * x1, yf * y1);
	vertf((float)x2, h->floor, (float)y2, l2, xf * x2, yf * y2);
	vertf((float)x3, h->floor, (float)y3, l3, xf * x3, yf * y3);
	addstrip(gltex, curvert - 3, 3);

    gltex = lookuptexture(h->ctex, sx, sy);
    xf = TEXTURESCALE/sx;
    yf = TEXTURESCALE/sy;
	gltex = lookuptexture(h->ctex, sx, sy);
	xf = TEXTURESCALE / sx;
	yf = TEXTURESCALE / sy;

    vertf((float)x3, h->ceil, (float)y3, l3, xf*x3, yf*y3);
    vertf((float)x2, h->ceil, (float)y2, l2, xf*x2, yf*y2);
    vertf((float)x1, h->ceil, (float)y1, l1, xf*x1, yf*y1);
    addstrip(gltex, curvert-3, 3);
    nquads++;
	vertf((float)x3, h->ceil, (float)y3, l3, xf * x3, yf * y3);
	vertf((float)x2, h->ceil, (float)y2, l2, xf * x2, yf * y2);
	vertf((float)x1, h->ceil, (float)y1, l1, xf * x1, yf * y1);
	addstrip(gltex, curvert - 3, 3);
	nquads++;
};

void
void render_tris(int x, int y, int size, bool topleft,
                 sqr *h1, sqr *h2, sqr *s, sqr *t, sqr *u, sqr *v)
render_tris(int x, int y, int size, bool topleft, sqr *h1, sqr *h2, sqr *s,
    sqr *t, sqr *u, sqr *v)
{
    if(topleft)
	if (topleft) {
    {
        if(h1) render_2tris(h1, s, x+size, y+size, x, y+size, x, y, u, v, s);
        if(h2) render_2tris(h2, s, x, y, x+size, y, x+size, y+size, s, t, v);
		if (h1)
			render_2tris(h1, s, x + size, y + size, x, y + size, x,
			    y, u, v, s);
		if (h2)
			render_2tris(h2, s, x, y, x + size, y, x + size,
    }
    else
			    y + size, s, t, v);
	} else {
    {
        if(h1) render_2tris(h1, s, x, y, x+size, y, x, y+size, s, t, u);
        if(h2) render_2tris(h2, s, x+size, y, x+size, y+size, x, y+size, t, u, v);
		if (h1)
			render_2tris(
			    h1, s, x, y, x + size, y, x, y + size, s, t, u);
		if (h2)
			render_2tris(h2, s, x + size, y, x + size, y + size, x,
    };
};
			    y + size, t, u, v);
	};
};

void
void render_square(int wtex, float floor1, float floor2, float ceil1, float ceil2, int x1, int y1, int x2, int y2, int size, sqr *l1, sqr *l2, bool flip)   // wall quads
render_square(int wtex, float floor1, float floor2, float ceil1, float ceil2,
    int x1, int y1, int x2, int y2, int size, sqr *l1, sqr *l2,
    bool flip) // wall quads
{
    stripend();
    vertcheck();
    if(showm) { l1 = &sbright; l2 = &sdark; };
	stripend();
	vertcheck();
	if (showm) {
		l1 = &sbright;
		l2 = &sdark;
	};

    int sx, sy;
    int gltex = lookuptexture(wtex, sx, sy);
    float xf = TEXTURESCALE/sx;
    float yf = TEXTURESCALE/sy;
    float xs = size*xf;
    float xo = xf*(x1==x2 ? min(y1,y2) : min(x1,x2));
	int sx, sy;
	int gltex = lookuptexture(wtex, sx, sy);
	float xf = TEXTURESCALE / sx;
	float yf = TEXTURESCALE / sy;
	float xs = size * xf;
	float xo = xf * (x1 == x2 ? min(y1, y2) : min(x1, x2));

    if(!flip)
	if (!flip) {
    {
        vertf((float)x2, ceil2,  (float)y2, l2, xo+xs, -yf*ceil2);
        vertf((float)x1, ceil1,  (float)y1, l1, xo,    -yf*ceil1); 
        vertf((float)x2, floor2, (float)y2, l2, xo+xs, -floor2*yf); 
        vertf((float)x1, floor1, (float)y1, l1, xo,    -floor1*yf); 
		vertf((float)x2, ceil2, (float)y2, l2, xo + xs, -yf * ceil2);
		vertf((float)x1, ceil1, (float)y1, l1, xo, -yf * ceil1);
		vertf((float)x2, floor2, (float)y2, l2, xo + xs, -floor2 * yf);
		vertf((float)x1, floor1, (float)y1, l1, xo, -floor1 * yf);
    }
    else
	} else {
    {
        vertf((float)x1, ceil1,  (float)y1, l1, xo,    -yf*ceil1);
        vertf((float)x2, ceil2,  (float)y2, l2, xo+xs, -yf*ceil2); 
        vertf((float)x1, floor1, (float)y1, l1, xo,    -floor1*yf); 
        vertf((float)x2, floor2, (float)y2, l2, xo+xs, -floor2*yf); 
    };
		vertf((float)x1, ceil1, (float)y1, l1, xo, -yf * ceil1);
		vertf((float)x2, ceil2, (float)y2, l2, xo + xs, -yf * ceil2);
		vertf((float)x1, floor1, (float)y1, l1, xo, -floor1 * yf);
		vertf((float)x2, floor2, (float)y2, l2, xo + xs, -floor2 * yf);
	};

    nquads++;
    addstrip(gltex, curvert-4, 4);
	nquads++;
	addstrip(gltex, curvert - 4, 4);
};

int wx1, wy1, wx2, wy2;

VAR(watersubdiv, 1, 4, 64);
VARF(waterlevel, -128, -128, 127, if(!noteditmode()) hdr.waterlevel = waterlevel);
VARF(waterlevel, -128, -128, 127,
    if (!noteditmode()) hdr.waterlevel = waterlevel);

inline void
inline void vertw(int v1, float v2, int v3, sqr *c, float t1, float t2, float t)
vertw(int v1, float v2, int v3, sqr *c, float t1, float t2, float t)
{
    vertcheck();
    vertf((float)v1, v2-(float)sin(v1*v3*0.1+t)*0.2f, (float)v3, c, t1, t2);
	vertcheck();
	vertf((float)v1, v2 - (float)sin(v1 * v3 * 0.1 + t) * 0.2f, (float)v3,
	    c, t1, t2);
};

inline float dx(float x) { return x+(float)sin(x*2+lastmillis/1000.0f)*0.04f; };
inline float dy(float x) { return x+(float)sin(x*2+lastmillis/900.0f+PI/5)*0.05f; };

// renders water for bounding rect area that contains water... simple but very inefficient
inline float
dx(float x)
{
	return x + (float)sin(x * 2 + lastmillis / 1000.0f) * 0.04f;
};
inline float
dy(float x)
{
	return x + (float)sin(x * 2 + lastmillis / 900.0f + PI / 5) * 0.05f;
};

// renders water for bounding rect area that contains water... simple but very
// inefficient

int
int renderwater(float hf)
renderwater(float hf)
{
	if (wx1 < 0)
    if(wx1<0) return nquads;
		return nquads;

    glDepthMask(GL_FALSE);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_SRC_COLOR);
    int sx, sy;
    glBindTexture(GL_TEXTURE_2D, lookuptexture(DEFAULT_LIQUID, sx, sy));  
	glDepthMask(GL_FALSE);
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_SRC_COLOR);
	int sx, sy;
	glBindTexture(GL_TEXTURE_2D, lookuptexture(DEFAULT_LIQUID, sx, sy));

    wx1 &= ~(watersubdiv-1);
    wy1 &= ~(watersubdiv-1);
	wx1 &= ~(watersubdiv - 1);
	wy1 &= ~(watersubdiv - 1);

    float xf = TEXTURESCALE/sx;
    float yf = TEXTURESCALE/sy;
    float xs = watersubdiv*xf;
    float ys = watersubdiv*yf;
    float t1 = lastmillis/300.0f;
    float t2 = lastmillis/4000.0f;
    
    sqr dl;
    dl.r = dl.g = dl.b = 255;
    
    for(int xx = wx1; xx<wx2; xx += watersubdiv)
	float xf = TEXTURESCALE / sx;
	float yf = TEXTURESCALE / sy;
	float xs = watersubdiv * xf;
	float ys = watersubdiv * yf;
	float t1 = lastmillis / 300.0f;
	float t2 = lastmillis / 4000.0f;

	sqr dl;
	dl.r = dl.g = dl.b = 255;

	for (int xx = wx1; xx < wx2; xx += watersubdiv) {
    {
        for(int yy = wy1; yy<wy2; yy += watersubdiv)
		for (int yy = wy1; yy < wy2; yy += watersubdiv) {
        {
            float xo = xf*(xx+t2);
            float yo = yf*(yy+t2);
            if(yy==wy1)
			float xo = xf * (xx + t2);
			float yo = yf * (yy + t2);
			if (yy == wy1) {
            {
                vertw(xx,             hf, yy,             &dl, dx(xo),    dy(yo), t1);
                vertw(xx+watersubdiv, hf, yy,             &dl, dx(xo+xs), dy(yo), t1);
            };
            vertw(xx,             hf, yy+watersubdiv, &dl, dx(xo),    dy(yo+ys), t1);
            vertw(xx+watersubdiv, hf, yy+watersubdiv, &dl, dx(xo+xs), dy(yo+ys), t1); 
        };   
        int n = (wy2-wy1-1)/watersubdiv;
        nquads += n;
        n = (n+2)*2;
        glDrawArrays(GL_TRIANGLE_STRIP, curvert -= n, n);
    };
    
    glDisable(GL_BLEND);
    glDepthMask(GL_TRUE);
    
    return nquads;
				vertw(xx, hf, yy, &dl, dx(xo), dy(yo), t1);
				vertw(xx + watersubdiv, hf, yy, &dl,
				    dx(xo + xs), dy(yo), t1);
			};
			vertw(xx, hf, yy + watersubdiv, &dl, dx(xo),
			    dy(yo + ys), t1);
			vertw(xx + watersubdiv, hf, yy + watersubdiv, &dl,
			    dx(xo + xs), dy(yo + ys), t1);
		};
		int n = (wy2 - wy1 - 1) / watersubdiv;
		nquads += n;
		n = (n + 2) * 2;
		glDrawArrays(GL_TRIANGLE_STRIP, curvert -= n, n);
	};

	glDisable(GL_BLEND);
	glDepthMask(GL_TRUE);

	return nquads;
};

void
void addwaterquad(int x, int y, int size)       // update bounding rect that contains water
addwaterquad(int x, int y, int size) // update bounding rect that contains water
{
    int x2 = x+size;
    int y2 = y+size;
    if(wx1<0)
	int x2 = x + size;
	int y2 = y + size;
	if (wx1 < 0) {
    {
        wx1 = x;
        wy1 = y;
        wx2 = x2;
        wy2 = y2;
		wx1 = x;
		wy1 = y;
		wx2 = x2;
		wy2 = y2;
    }
    else
	} else {
    {
        if(x<wx1) wx1 = x;
        if(y<wy1) wy1 = y;
        if(x2>wx2) wx2 = x2;
        if(y2>wy2) wy2 = y2;
    };
		if (x < wx1)
			wx1 = x;
		if (y < wy1)
			wy1 = y;
		if (x2 > wx2)
			wx2 = x2;
		if (y2 > wy2)
			wy2 = y2;
	};
};

void
void resetcubes()
resetcubes()
{
	if (!verts)
    if(!verts) reallocv();
    floorstrip = deltastrip = false;
    wx1 = -1;
    nquads = 0;
    sbright.r = sbright.g = sbright.b = 255;
    sdark.r = sdark.g = sdark.b = 0;
		reallocv();
	floorstrip = deltastrip = false;
	wx1 = -1;
	nquads = 0;
	sbright.r = sbright.g = sbright.b = 255;
	sdark.r = sdark.g = sdark.b = 0;
};