X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=share%2Fsolid_gl.c;h=82e3bb6de12a5dd4957552fda0b88fa55006a26d;hb=4483dfdacd29073b37a6429ca8e123c80deac75a;hp=69a5196de19311081be2969301de493818ba5475;hpb=6090d148f456c8d0153655b14fdc95888ed993ce;p=neverball diff --git a/share/solid_gl.c b/share/solid_gl.c index 69a5196..82e3bb6 100644 --- a/share/solid_gl.c +++ b/share/solid_gl.c @@ -25,7 +25,9 @@ #include "image.h" #include "base_image.h" #include "solid_gl.h" +#include "solid_all.h" #include "base_config.h" +#include "lang.h" /*---------------------------------------------------------------------------*/ @@ -71,15 +73,30 @@ static int sol_enum_body(const struct s_file *fp, /*---------------------------------------------------------------------------*/ -#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, "" @@ -99,7 +116,7 @@ static const struct s_mtrl *sol_draw_mtrl(const struct s_file *fp, 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. */ @@ -124,8 +141,6 @@ static const struct s_mtrl *sol_draw_mtrl(const struct s_file *fp, { glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); - - glBindTexture(GL_TEXTURE_2D, mp->o); } /* Enable additive blending. */ @@ -138,6 +153,22 @@ static const struct s_mtrl *sol_draw_mtrl(const struct s_file *fp, 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)) @@ -154,14 +185,14 @@ static const struct s_mtrl *sol_draw_mtrl(const struct s_file *fp, 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) { @@ -192,10 +223,10 @@ static const struct s_mtrl *sol_draw_bill(const struct s_file *fp, 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(); } @@ -205,6 +236,8 @@ static const struct s_mtrl *sol_draw_bill(const struct s_file *fp, return mp; } +/*---------------------------------------------------------------------------*/ + void sol_back(const struct s_file *fp, float n, float f, float t) { const struct s_mtrl *mp = &default_mtrl; @@ -218,7 +251,7 @@ void sol_back(const struct s_file *fp, float n, float f, float t) { 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); } @@ -280,14 +313,15 @@ static void sol_draw_lump(const struct s_file *fp, 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)) { @@ -314,15 +348,20 @@ static const struct s_mtrl *sol_draw_body(const struct s_file *fp, 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. */ @@ -331,7 +370,7 @@ static void sol_draw_list(const struct s_file *fp, glPopMatrix(); } -void sol_draw(const struct s_file *fp) +void sol_draw(const struct s_file *fp, int depthmask, int depthtest) { int bi; @@ -343,13 +382,61 @@ void sol_draw(const struct s_file *fp) /* 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) @@ -395,7 +482,8 @@ static void sol_shad_lump(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; @@ -408,7 +496,7 @@ static void sol_shad_body(const struct s_file *fp, 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); @@ -425,15 +513,20 @@ static void sol_shad_body(const struct s_file *fp, 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. */ @@ -441,6 +534,7 @@ static void sol_shad_list(const struct s_file *fp, { glPushMatrix(); glTranslatef(p[0], p[2], 0.0f); + glRotatef(-a, u[0], u[2], u[1]); } glMatrixMode(GL_MODELVIEW); @@ -501,8 +595,8 @@ static void sol_load_objects(struct s_file *fp, int s) { 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(); @@ -519,8 +613,8 @@ static void sol_load_objects(struct s_file *fp, int s) { 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(); @@ -537,7 +631,7 @@ static void sol_load_objects(struct s_file *fp, int s) { 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(); @@ -552,9 +646,9 @@ static void sol_load_objects(struct s_file *fp, int s) 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(); } @@ -587,14 +681,14 @@ static GLuint sol_find_texture(const char *name) 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. */ @@ -613,11 +707,11 @@ static void sol_load_textures(struct s_file *fp, int k) /*---------------------------------------------------------------------------*/ -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; }