#include "image.h"
#include "base_image.h"
#include "solid_gl.h"
+#include "solid_all.h"
#include "base_config.h"
+#include "lang.h"
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
-#define color_cmp(a, b) ((a)[0] == (b)[0] && \
- (a)[1] == (b)[1] && \
- (a)[2] == (b)[2] && \
- (a)[3] == (b)[3])
+int sol_reflective(const struct s_file *fp)
+{
+ int bi;
+
+ for (bi = 0; bi < fp->bc; bi++)
+ if (fp->bv[bi].rl)
+ return 1;
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+#define tobyte(f) ((GLubyte) (f * 255.0f))
+
+#define color_cmp(a, b) (tobyte((a)[0]) == tobyte((b)[0]) && \
+ tobyte((a)[1]) == tobyte((b)[1]) && \
+ tobyte((a)[2]) == tobyte((b)[2]) && \
+ tobyte((a)[3]) == tobyte((b)[3]))
static struct s_mtrl default_mtrl =
{
- { 0.2f, 0.2f, 0.2f, 1.0f },
{ 0.8f, 0.8f, 0.8f, 1.0f },
+ { 0.2f, 0.2f, 0.2f, 1.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f },
{ 0.0f, }, 0.0f, M_OPAQUE, 0, ""
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mp->s);
if (!color_cmp(mp->e, mq->e))
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mp->e);
- if (mp->h[0] != mq->h[0])
+ if (tobyte(mp->h[0]) != tobyte(mq->h[0]))
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mp->h);
/* Bind the texture. */
{
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
-
- glBindTexture(GL_TEXTURE_2D, mp->o);
}
/* Enable additive blending. */
if ((mq->fl & M_ADDITIVE) && !(mp->fl & M_ADDITIVE))
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ /* Enable visibility-from-behind. */
+
+ if ((mp->fl & M_TWO_SIDED) && !(mq->fl & M_TWO_SIDED))
+ {
+ glDisable(GL_CULL_FACE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
+ }
+
+ /* Disable visibility-from-behind. */
+
+ if ((mq->fl & M_TWO_SIDED) && !(mp->fl & M_TWO_SIDED))
+ {
+ glEnable(GL_CULL_FACE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+ }
+
/* Enable decal offset. */
if ((mp->fl & M_DECAL) && !(mq->fl & M_DECAL))
return mp;
}
-static const struct s_mtrl *sol_draw_bill(const struct s_file *fp,
+static const struct s_mtrl *sol_back_bill(const struct s_file *fp,
const struct s_bill *rp,
const struct s_mtrl *mp, float t)
{
- float T = fmodf(t, rp->t) - rp->t / 2;
+ float T = (rp->t > 0.0f) ? (fmodf(t, rp->t) - rp->t / 2) : 0.0f;
- float w = rp->w[0] + rp->w[1] * T + rp->w[2] * T * T;
- float h = rp->h[0] + rp->h[1] * T + rp->h[2] * T * T;
+ float w = rp->w[0] + rp->w[1] * T + rp->w[2] * T * T;
+ float h = rp->h[0] + rp->h[1] * T + rp->h[2] * T * T;
if (w > 0 && h > 0)
{
glBegin(GL_QUADS);
{
- glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, y0);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, y0);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, y1);
- glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, y1);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, y0);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, y0);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, y1);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, y1);
}
glEnd();
}
return mp;
}
+/*---------------------------------------------------------------------------*/
+
void sol_back(const struct s_file *fp, float n, float f, float t)
{
const struct s_mtrl *mp = &default_mtrl;
{
for (ri = 0; ri < fp->rc; ri++)
if (n <= fp->rv[ri].d && fp->rv[ri].d < f)
- mp = sol_draw_bill(fp, fp->rv + ri, mp, t);
+ mp = sol_back_bill(fp, fp->rv + ri, mp, t);
mp = sol_draw_mtrl(fp, &default_mtrl, mp);
}
static const struct s_mtrl *sol_draw_body(const struct s_file *fp,
const struct s_body *bp,
- const struct s_mtrl *mp, int fl)
+ const struct s_mtrl *mp,
+ int fl, int decal)
{
int mi, li, gi;
/* Iterate all materials of the correct opacity. */
for (mi = 0; mi < fp->mc; mi++)
- if ((fp->mv[mi].fl & fl) == fl)
+ if ((fp->mv[mi].fl & fl) && (fp->mv[mi].fl & M_DECAL) == decal)
{
if (sol_enum_mtrl(fp, bp, mi))
{
static void sol_draw_list(const struct s_file *fp,
const struct s_body *bp, GLuint list)
{
- float p[3];
+ float p[3], e[4], u[3], a;
+
+ sol_body_p(p, fp, bp->pi, bp->t);
+ sol_body_e(e, fp, bp, 0);
- sol_body_p(p, fp, bp);
+ q_as_axisangle(e, u, &a);
+ a = V_DEG(a);
glPushMatrix();
{
- /* Translate a moving body. */
+ /* Translate and rotate a moving body. */
glTranslatef(p[0], p[1], p[2]);
+ glRotatef(a, u[0], u[1], u[2]);
/* Draw the body. */
glPopMatrix();
}
-void sol_draw(const struct s_file *fp)
+void sol_draw(const struct s_file *fp, int depthmask, int depthtest)
{
int bi;
/* Render all translucent geometry into only the color buffer. */
- glDepthMask(GL_FALSE);
+ if (depthtest == 0) glDisable(GL_DEPTH_TEST);
+ if (depthmask == 0) glDepthMask(GL_FALSE);
{
for (bi = 0; bi < fp->bc; bi++)
if (fp->bv[bi].tl)
sol_draw_list(fp, fp->bv + bi, fp->bv[bi].tl);
}
- glDepthMask(GL_TRUE);
+ if (depthmask == 0) glDepthMask(GL_TRUE);
+ if (depthtest == 0) glEnable(GL_DEPTH_TEST);
+}
+
+void sol_bill(const struct s_file *fp, const float *M, float t)
+{
+ const struct s_mtrl *mp = &default_mtrl;
+
+ int ri;
+
+ for (ri = 0; ri < fp->rc; ++ri)
+ {
+ const struct s_bill *rp = fp->rv + ri;
+
+ float T = rp->t * t;
+ float S = fsinf(T);
+
+ float w = rp->w [0] + rp->w [1] * T + rp->w [2] * S;
+ float h = rp->h [0] + rp->h [1] * T + rp->h [2] * S;
+ float rx = rp->rx[0] + rp->rx[1] * T + rp->rx[2] * S;
+ float ry = rp->ry[0] + rp->ry[1] * T + rp->ry[2] * S;
+ float rz = rp->rz[0] + rp->rz[1] * T + rp->rz[2] * S;
+
+ mp = sol_draw_mtrl(fp, fp->mv + rp->mi, mp);
+
+ glPushMatrix();
+ {
+ glTranslatef(rp->p[0], rp->p[1], rp->p[2]);
+
+ if (M && ((rp->fl & B_NOFACE) == 0)) glMultMatrixf(M);
+
+ if (fabsf(rx) > 0.0f) glRotatef(rx, 1.0f, 0.0f, 0.0f);
+ if (fabsf(ry) > 0.0f) glRotatef(ry, 0.0f, 1.0f, 0.0f);
+ if (fabsf(rz) > 0.0f) glRotatef(rz, 0.0f, 0.0f, 1.0f);
+
+ glBegin(GL_QUADS);
+ {
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, -h / 2);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, -h / 2);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, +h / 2);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, +h / 2);
+ }
+ glEnd();
+ }
+ glPopMatrix();
+ }
+
+ mp = sol_draw_mtrl(fp, &default_mtrl, mp);
}
void sol_refl(const struct s_file *fp)
}
static void sol_shad_body(const struct s_file *fp,
- const struct s_body *bp, int fl)
+ const struct s_body *bp,
+ int fl, int decal)
{
int mi, li, gi;
glBegin(GL_TRIANGLES);
{
for (mi = 0; mi < fp->mc; mi++)
- if ((fp->mv[mi].fl & fl) == fl)
+ if ((fp->mv[mi].fl & fl) && (fp->mv[mi].fl & M_DECAL) == decal)
{
for (li = 0; li < bp->lc; li++)
sol_shad_lump(fp, fp->lv + bp->l0 + li, mi);
static void sol_shad_list(const struct s_file *fp,
const struct s_body *bp, GLuint list)
{
- float p[3];
+ float p[3], e[4], u[3], a;
+
+ sol_body_p(p, fp, bp->pi, bp->t);
+ sol_body_e(e, fp, bp, 0);
- sol_body_p(p, fp, bp);
+ q_as_axisangle(e, u, &a);
+ a = V_DEG(a);
glPushMatrix();
{
- /* Translate a moving body. */
+ /* Translate and rotate a moving body. */
glTranslatef(p[0], p[1], p[2]);
+ glRotatef(a, u[0], u[1], u[2]);
/* Translate the shadow on a moving body. */
{
glPushMatrix();
glTranslatef(p[0], p[2], 0.0f);
+ glRotatef(-a, u[0], u[2], u[1]);
}
glMatrixMode(GL_MODELVIEW);
{
const struct s_mtrl *mp = &default_mtrl;
- mp = sol_draw_body(fp, fp->bv + i, mp, M_OPAQUE);
- mp = sol_draw_body(fp, fp->bv + i, mp, M_OPAQUE | M_DECAL);
+ mp = sol_draw_body(fp, fp->bv + i, mp, M_OPAQUE, 0);
+ mp = sol_draw_body(fp, fp->bv + i, mp, M_OPAQUE, M_DECAL);
mp = sol_draw_mtrl(fp, &default_mtrl, mp);
}
glEndList();
{
const struct s_mtrl *mp = &default_mtrl;
- mp = sol_draw_body(fp, fp->bv + i, mp, M_TRANSPARENT | M_DECAL);
- mp = sol_draw_body(fp, fp->bv + i, mp, M_TRANSPARENT);
+ mp = sol_draw_body(fp, fp->bv + i, mp, M_TRANSPARENT, M_DECAL);
+ mp = sol_draw_body(fp, fp->bv + i, mp, M_TRANSPARENT, 0);
mp = sol_draw_mtrl(fp, &default_mtrl, mp);
}
glEndList();
{
const struct s_mtrl *mp = &default_mtrl;
- mp = sol_draw_body(fp, fp->bv + i, mp, M_REFLECTIVE);
+ mp = sol_draw_body(fp, fp->bv + i, mp, M_REFLECTIVE, 0);
mp = sol_draw_mtrl(fp, &default_mtrl, mp);
}
glEndList();
glNewList(fp->bv[i].sl, GL_COMPILE);
{
- if (on) sol_shad_body(fp, fp->bv + i, M_OPAQUE);
- if (rn) sol_shad_body(fp, fp->bv + i, M_REFLECTIVE);
- if (dn) sol_shad_body(fp, fp->bv + i, M_OPAQUE | M_DECAL);
+ if (on) sol_shad_body(fp, fp->bv + i, M_OPAQUE, 0);
+ if (rn) sol_shad_body(fp, fp->bv + i, M_REFLECTIVE, 0);
+ if (dn) sol_shad_body(fp, fp->bv + i, M_OPAQUE, M_DECAL);
}
glEndList();
}
return 0;
}
-static void sol_load_textures(struct s_file *fp, int k)
+static void sol_load_textures(struct s_file *fp)
{
int i;
/* Load the image referenced by each material. */
for (i = 0; i < fp->mc; i++)
- if ((fp->mv[i].o = sol_find_texture(fp->mv[i].f)))
+ if ((fp->mv[i].o = sol_find_texture(_(fp->mv[i].f))))
{
/* Set the texture to clamp or repeat based on material type. */
/*---------------------------------------------------------------------------*/
-int sol_load_gl(struct s_file *fp, const char *filename, int k, int s)
+int sol_load_gl(struct s_file *fp, const char *filename, int s)
{
if (sol_load_only_file(fp, filename))
{
- sol_load_textures(fp, k);
+ sol_load_textures(fp);
sol_load_objects (fp, s);
return 1;
}