git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@5687 e016b1c5-ed68-44aa-a2f7-31cac88cffde
283 lines
6.7 KiB
C++
283 lines
6.7 KiB
C++
#include "cube.h"
|
|
|
|
int wx1, wy1, wx2, wy2;
|
|
float wsx1, wsy1, wsx2, wsy2;
|
|
|
|
VARP(watersubdiv, 1, 4, 64);
|
|
VARF(waterlevel, -128, -128, 127, if(!noteditmode("waterlevel")) hdr.waterlevel = waterlevel);
|
|
|
|
void setwatercolor(const char *r, const char *g, const char *b, const char *a)
|
|
{
|
|
if(r[0])
|
|
{
|
|
hdr.watercolor[0] = ATOI(r);
|
|
hdr.watercolor[1] = ATOI(g);
|
|
hdr.watercolor[2] = ATOI(b);
|
|
hdr.watercolor[3] = a[0] ? ATOI(a) : 178;
|
|
}
|
|
else
|
|
{
|
|
hdr.watercolor[0] = 20;
|
|
hdr.watercolor[1] = 25;
|
|
hdr.watercolor[2] = 20;
|
|
hdr.watercolor[3] = 178;
|
|
}
|
|
}
|
|
|
|
COMMANDN(watercolour, setwatercolor, ARG_4STR);
|
|
|
|
// renders water for bounding rect area that contains water... simple but very inefficient
|
|
|
|
#define VERTW(vertw, body) \
|
|
inline void vertw(float v1, float v2, float v3, float t) \
|
|
{ \
|
|
float angle = v1*v2*0.1f + t; \
|
|
float h = 0.3f*sinf(angle); \
|
|
body; \
|
|
glVertex3f(v1, v2, v3+h); \
|
|
}
|
|
#define VERTWT(vertwt, body) VERTW(vertwt, { float v = cosf(angle); float duv = 0.2f*v; body; })
|
|
VERTW(vertw, {})
|
|
VERTW(vertwc, {
|
|
float v = cosf(angle);
|
|
glColor4ub(hdr.watercolor[0], hdr.watercolor[1], hdr.watercolor[2], (uchar)(hdr.watercolor[3] + (max(v, 0.0f) - 0.5f)*51.0f));
|
|
})
|
|
VERTWT(vertwt, {
|
|
glTexCoord3f(v1+duv, v2+duv, v3+h);
|
|
})
|
|
VERTWT(vertwtc, {
|
|
glColor4f(1, 1, 1, 0.15f + max(v, 0.0f)*0.15f);
|
|
glTexCoord3f(v1+duv, v2+duv, v3+h);
|
|
})
|
|
VERTWT(vertwmtc, {
|
|
glColor4f(1, 1, 1, 0.15f + max(v, 0.0f)*0.15f);
|
|
glMultiTexCoord3f_(GL_TEXTURE0_ARB, v1-duv, v2+duv, v3+h);
|
|
glMultiTexCoord3f_(GL_TEXTURE1_ARB, v1+duv, v2+duv, v3+h);
|
|
})
|
|
|
|
extern int nquads;
|
|
|
|
#define renderwaterstrips(vertw, hf, t) \
|
|
for(int x = wx1; x<wx2; x += watersubdiv) \
|
|
{ \
|
|
glBegin(GL_TRIANGLE_STRIP); \
|
|
vertw(x, wy1, hf, t); \
|
|
vertw(x+watersubdiv, wy1, hf, t); \
|
|
for(int y = wy1; y<wy2; y += watersubdiv) \
|
|
{ \
|
|
vertw(x, y+watersubdiv, hf, t); \
|
|
vertw(x+watersubdiv, y+watersubdiv, hf, t); \
|
|
} \
|
|
glEnd(); \
|
|
nquads += (wy2-wy1-1)/watersubdiv; \
|
|
}
|
|
|
|
void setprojtexmatrix()
|
|
{
|
|
glmatrixf projtex = mvpmatrix;
|
|
projtex.projective();
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
glLoadMatrixf(projtex.v);
|
|
}
|
|
|
|
void setupmultitexrefract(GLuint reflecttex, GLuint refracttex)
|
|
{
|
|
setuptmu(0, "K , T @ Ka");
|
|
|
|
colortmu(0, hdr.watercolor[0]/255.0f, hdr.watercolor[1]/255.0f, hdr.watercolor[2]/255.0f, hdr.watercolor[3]/255.0f);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, refracttex);
|
|
setprojtexmatrix();
|
|
|
|
glActiveTexture_(GL_TEXTURE1_ARB);
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
setuptmu(1, "P , T @ C~a");
|
|
|
|
glBindTexture(GL_TEXTURE_2D, reflecttex);
|
|
setprojtexmatrix();
|
|
|
|
glActiveTexture_(GL_TEXTURE0_ARB);
|
|
}
|
|
|
|
void setupmultitexreflect(GLuint reflecttex)
|
|
{
|
|
setuptmu(0, "T , K @ Ca", "Ka * P~a");
|
|
|
|
float a = hdr.watercolor[3]/255.0f;
|
|
colortmu(0, hdr.watercolor[0]/255.0f*a, hdr.watercolor[1]/255.0f*a, hdr.watercolor[2]/255.0f*a, 1.0f-a);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, reflecttex);
|
|
setprojtexmatrix();
|
|
}
|
|
|
|
void cleanupmultitex(GLuint reflecttex, GLuint refracttex)
|
|
{
|
|
resettmu(0);
|
|
glLoadIdentity();
|
|
|
|
if(refracttex)
|
|
{
|
|
glActiveTexture_(GL_TEXTURE1_ARB);
|
|
glDisable(GL_TEXTURE_2D);
|
|
resettmu(1);
|
|
glLoadIdentity();
|
|
glActiveTexture_(GL_TEXTURE0_ARB);
|
|
}
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
|
|
VARP(mtwater, 0, 1, 1);
|
|
|
|
int renderwater(float hf, GLuint reflecttex, GLuint refracttex)
|
|
{
|
|
if(wx1<0) return nquads;
|
|
|
|
wx1 -= wx1%watersubdiv;
|
|
wy1 -= wy1%watersubdiv;
|
|
|
|
float t = lastmillis/300.0f;
|
|
|
|
if(mtwater && maxtmus>=2 && reflecttex)
|
|
{
|
|
if(refracttex)
|
|
{
|
|
setupmultitexrefract(reflecttex, refracttex);
|
|
renderwaterstrips(vertwmtc, hf, t);
|
|
}
|
|
else
|
|
{
|
|
setupmultitexreflect(reflecttex);
|
|
glDepthMask(GL_FALSE);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_ONE, GL_SRC_ALPHA);
|
|
renderwaterstrips(vertwtc, hf, t);
|
|
glDisable(GL_BLEND);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
cleanupmultitex(reflecttex, refracttex);
|
|
|
|
return nquads;
|
|
}
|
|
|
|
if(!refracttex)
|
|
{
|
|
glDisable(GL_TEXTURE_2D);
|
|
glEnable(GL_BLEND);
|
|
}
|
|
glDepthMask(GL_FALSE);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
if(reflecttex)
|
|
{
|
|
if(!refracttex)
|
|
{
|
|
glColor4ubv(hdr.watercolor);
|
|
renderwaterstrips(vertw, hf, t);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
}
|
|
|
|
setprojtexmatrix();
|
|
|
|
glBindTexture(GL_TEXTURE_2D, refracttex ? refracttex : reflecttex);
|
|
}
|
|
|
|
if(refracttex)
|
|
{
|
|
glColor3f(1, 1, 1);
|
|
renderwaterstrips(vertwt, hf, t);
|
|
glEnable(GL_BLEND);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, reflecttex);
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
if(reflecttex) { renderwaterstrips(vertwtc, hf, t); }
|
|
else { renderwaterstrips(vertwc, hf, t); }
|
|
|
|
if(reflecttex)
|
|
{
|
|
glLoadIdentity();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
else glEnable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_BLEND);
|
|
if(!refracttex) glDepthMask(GL_TRUE);
|
|
|
|
return nquads;
|
|
}
|
|
|
|
void addwaterquad(int x, int y, int size) // update bounding rect that contains water
|
|
{
|
|
int x2 = x+size;
|
|
int y2 = y+size;
|
|
if(wx1<0)
|
|
{
|
|
wx1 = x;
|
|
wy1 = y;
|
|
wx2 = x2;
|
|
wy2 = y2;
|
|
}
|
|
else
|
|
{
|
|
if(x<wx1) wx1 = x;
|
|
if(y<wy1) wy1 = y;
|
|
if(x2>wx2) wx2 = x2;
|
|
if(y2>wy2) wy2 = y2;
|
|
}
|
|
}
|
|
|
|
void calcwaterscissor()
|
|
{
|
|
vec4 v[4];
|
|
float sx1 = 1, sy1 = 1, sx2 = -1, sy2 = -1;
|
|
loopi(4)
|
|
{
|
|
vec4 &p = v[i];
|
|
mvpmatrix.transform(vec(i&1 ? wx2 : wx1, i&2 ? wy2 : wy1, hdr.waterlevel-0.3f), p);
|
|
if(p.z >= 0)
|
|
{
|
|
float x = p.x / p.w, y = p.y / p.w;
|
|
sx1 = min(sx1, x);
|
|
sy1 = min(sy1, y);
|
|
sx2 = max(sx2, x);
|
|
sy2 = max(sy2, y);
|
|
}
|
|
}
|
|
if(sx1 >= sx2 || sy1 >= sy2)
|
|
{
|
|
sx1 = sy1 = -1;
|
|
sx2 = sy2 = 1;
|
|
}
|
|
else loopi(4)
|
|
{
|
|
const vec4 &p = v[i];
|
|
if(p.z >= 0) continue;
|
|
loopj(2)
|
|
{
|
|
const vec4 &o = v[i^(1<<j)];
|
|
if(o.z <= 0) continue;
|
|
float t = p.z/(p.z - o.z),
|
|
w = p.w + t*(o.w - p.w),
|
|
x = (p.x + t*(o.x - p.x))/w,
|
|
y = (p.y + t*(o.y - p.y))/w;
|
|
sx1 = min(sx1, x);
|
|
sy1 = min(sy1, y);
|
|
sx2 = max(sx2, x);
|
|
sy2 = max(sy2, y);
|
|
}
|
|
}
|
|
wsx1 = max(sx1, -1.0f);
|
|
wsy1 = max(sy1, -1.0f);
|
|
wsx2 = min(sx2, 1.0f);
|
|
wsy2 = min(sy2, 1.0f);
|
|
}
|
|
|
|
void resetwater()
|
|
{
|
|
if(!reflecting) wx1 = -1;
|
|
}
|
|
|