Fix accidental switch/teleporter behavior changes
[neverball] / share / solid_gl.c
index 7a46059..82e3bb6 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <SDL.h>
 #include <SDL_rwops.h>
-#include <SDL_image.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "glext.h"
 #include "vec3.h"
+#include "image.h"
 #include "base_image.h"
 #include "solid_gl.h"
+#include "solid_all.h"
 #include "base_config.h"
+#include "lang.h"
 
 /*---------------------------------------------------------------------------*/
 
@@ -56,7 +58,7 @@ static int sol_enum_mtrl(const struct s_file *fp,
 }
 
 static int sol_enum_body(const struct s_file *fp,
-                           const struct s_body *bp, int fl)
+                         const struct s_body *bp, int fl)
 {
     int mi, c = 0;
 
@@ -71,48 +73,126 @@ static int sol_enum_body(const struct s_file *fp,
 
 /*---------------------------------------------------------------------------*/
 
-static void sol_draw_mtrl(const struct s_file *fp, int i)
+int sol_reflective(const struct s_file *fp)
 {
-    const struct s_mtrl *mp = fp->mv + i;
+    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))
 
-    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,   mp->a);
-    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,   mp->d);
-    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,  mp->s);
-    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,  mp->e);
-    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mp->h);
+#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]))
 
-    if (mp->fl & M_ENVIRONMENT)
+static struct s_mtrl default_mtrl =
+{
+    { 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, ""
+};
+
+static const struct s_mtrl *sol_draw_mtrl(const struct s_file *fp,
+                                          const struct s_mtrl *mp,
+                                          const struct s_mtrl *mq)
+{
+    /* Change material properties only as needed. */
+
+    if (!color_cmp(mp->a, mq->a))
+        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,   mp->a);
+    if (!color_cmp(mp->d, mq->d))
+        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,   mp->d);
+    if (!color_cmp(mp->s, mq->s))
+        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 (tobyte(mp->h[0]) != tobyte(mq->h[0]))
+        glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mp->h);
+
+    /* Bind the texture. */
+
+    if (mp->o != mq->o)
+        glBindTexture(GL_TEXTURE_2D, mp->o);
+
+    /* Enable environment mapping. */
+
+    if ((mp->fl & M_ENVIRONMENT) && !(mq->fl & M_ENVIRONMENT))
     {
         glEnable(GL_TEXTURE_GEN_S);
         glEnable(GL_TEXTURE_GEN_T);
 
-        glBindTexture(GL_TEXTURE_2D, mp->o);
-
         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
     }
-    else
+
+    /* Disable environment mapping. */
+
+    if ((mq->fl & M_ENVIRONMENT) && !(mp->fl & M_ENVIRONMENT))
     {
         glDisable(GL_TEXTURE_GEN_S);
         glDisable(GL_TEXTURE_GEN_T);
-
-        glBindTexture(GL_TEXTURE_2D, mp->o);
     }
 
-    if (mp->fl & M_ADDITIVE)
+    /* Enable additive blending. */
+
+    if ((mp->fl & M_ADDITIVE) && !(mq->fl & M_ADDITIVE))
         glBlendFunc(GL_ONE, GL_ONE);
-    else
+
+    /* Enable standard 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))
+    {
+        glEnable(GL_POLYGON_OFFSET_FILL);
+        glPolygonOffset(-1.0f, -2.0f);
+    }
+
+    /* Disable decal offset. */
+
+    if ((mq->fl & M_DECAL) && !(mp->fl & M_DECAL))
+        glDisable(GL_POLYGON_OFFSET_FILL);
+
+    return mp;
 }
 
-static void sol_draw_bill(const struct s_file *fp,
-                          const struct s_bill *rp, float t)
+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)
     {
@@ -139,37 +219,44 @@ static void sol_draw_bill(const struct s_file *fp,
 
             glRotatef(rz, 0.0f, 0.0f, 1.0f);
 
-            sol_draw_mtrl(fp, rp->mi);
+            mp = sol_draw_mtrl(fp, fp->mv + rp->mi, mp);
 
             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();
         }
         glPopMatrix();
     }
+
+    return mp;
 }
 
+/*---------------------------------------------------------------------------*/
+
 void sol_back(const struct s_file *fp, float n, float f, float t)
 {
-    int ri;
+    const struct s_mtrl *mp = &default_mtrl;
 
-    glPushAttrib(GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT);
-    {
-        /* Render all billboards in the given range. */
+    int ri;
 
-        glDisable(GL_LIGHTING);
-        glDepthMask(GL_FALSE);
+    /* Render all billboards in the given range. */
 
+    glDisable(GL_LIGHTING);
+    glDepthMask(GL_FALSE);
+    {
         for (ri = 0; ri < fp->rc; ri++)
             if (n <= fp->rv[ri].d && fp->rv[ri].d < f)
-                sol_draw_bill(fp, fp->rv + ri, t);
+                mp = sol_back_bill(fp, fp->rv + ri, mp, t);
+
+        mp = sol_draw_mtrl(fp, &default_mtrl, mp);
     }
-    glPopAttrib();
+    glDepthMask(GL_TRUE);
+    glEnable(GL_LIGHTING);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -224,21 +311,23 @@ static void sol_draw_lump(const struct s_file *fp,
         sol_draw_geom(fp, fp->gv + fp->iv[lp->g0 + i], mi);
 }
 
-static void sol_draw_body(const struct s_file *fp,
-                          const struct s_body *bp, int fl)
+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, 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)
+        if ((fp->mv[mi].fl & fl) && (fp->mv[mi].fl & M_DECAL) == decal)
         {
             if (sol_enum_mtrl(fp, bp, mi))
             {
                 /* Set the material state. */
 
-                sol_draw_mtrl(fp, mi);
+                mp = sol_draw_mtrl(fp, fp->mv + mi, mp);
 
                 /* Render all geometry of that material. */
 
@@ -252,20 +341,27 @@ static void sol_draw_body(const struct s_file *fp,
                 glEnd();
             }
         }
+
+    return mp;
 }
 
 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. */
 
@@ -274,51 +370,84 @@ 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;
 
-    glPushAttrib(GL_TEXTURE_BIT      |
-                 GL_LIGHTING_BIT     |
-                 GL_COLOR_BUFFER_BIT |
-                 GL_DEPTH_BUFFER_BIT);
-    {
-        /* Render all opaque geometry into the color and depth buffers. */
-
-        for (bi = 0; bi < fp->bc; bi++)
-            if (fp->bv[bi].ol)
-                sol_draw_list(fp, fp->bv + bi, fp->bv[bi].ol);
-
-        /* Render all translucent geometry into only the color buffer. */
+    /* Render all opaque geometry into the color and depth buffers. */
 
-        glDepthMask(GL_FALSE);
+    for (bi = 0; bi < fp->bc; bi++)
+        if (fp->bv[bi].ol)
+            sol_draw_list(fp, fp->bv + bi, fp->bv[bi].ol);
 
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    /* Render all translucent geometry into only the color buffer. */
 
+    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);
     }
-    glPopAttrib();
+    if (depthmask == 0) glDepthMask(GL_TRUE);
+    if (depthtest == 0) glEnable(GL_DEPTH_TEST);
 }
 
-void sol_refl(const struct s_file *fp)
+void sol_bill(const struct s_file *fp, const float *M, float t)
 {
-    int bi;
+    const struct s_mtrl *mp = &default_mtrl;
+
+    int ri;
 
-    glPushAttrib(GL_LIGHTING_BIT);
+    for (ri = 0; ri < fp->rc; ++ri)
     {
-        /* Render all reflective geometry into the color and depth buffers. */
+        const struct s_bill *rp = fp->rv + ri;
 
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        float T = rp->t * t;
+        float S = fsinf(T);
 
-        for (bi = 0; bi < fp->bc; bi++)
-            if (fp->bv[bi].rl)
-                sol_draw_list(fp, fp->bv + bi, fp->bv[bi].rl);
+        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();
     }
-    glPopAttrib();
+
+    mp = sol_draw_mtrl(fp, &default_mtrl, mp);
+}
+
+void sol_refl(const struct s_file *fp)
+{
+    int bi;
+
+    /* Render all reflective geometry into the color and depth buffers. */
+
+    for (bi = 0; bi < fp->bc; bi++)
+        if (fp->bv[bi].rl)
+            sol_draw_list(fp, fp->bv + bi, fp->bv[bi].rl);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -353,14 +482,21 @@ 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;
 
+    if (fl & M_DECAL)
+    {
+        glEnable(GL_POLYGON_OFFSET_FILL);
+        glPolygonOffset(-1.0f, -2.0f);
+    }
+
     glBegin(GL_TRIANGLES);
     {
         for (mi = 0; mi < fp->mc; mi++)
-            if (fp->mv[mi].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);
@@ -369,20 +505,28 @@ static void sol_shad_body(const struct s_file *fp,
             }
     }
     glEnd();
+
+    if (fl & M_DECAL)
+        glDisable(GL_POLYGON_OFFSET_FILL);
 }
 
 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. */
 
@@ -390,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);
 
@@ -412,21 +557,15 @@ void sol_shad(const struct s_file *fp)
 {
     int bi;
 
-    glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT);
-    {
-        /* Render all shadowed geometry. */
-
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-        glDepthFunc(GL_LEQUAL);
-        glDepthMask(GL_FALSE);
+    /* Render all shadowed geometry. */
 
+    glDepthMask(GL_FALSE);
+    {
         for (bi = 0; bi < fp->bc; bi++)
             if (fp->bv[bi].sl)
                 sol_shad_list(fp, fp->bv + bi, fp->bv[bi].sl);
     }
-    glPopAttrib();
+    glDepthMask(GL_TRUE);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -435,33 +574,48 @@ static void sol_load_objects(struct s_file *fp, int s)
 {
     int i;
 
+    /* Here we sort geometry into display lists by material type. */
+
     for (i = 0; i < fp->bc; i++)
     {
         struct s_body *bp = fp->bv + i;
 
-        /* Draw all opaque geometry. */
+        int on = sol_enum_body(fp, bp, M_OPAQUE);
+        int tn = sol_enum_body(fp, bp, M_TRANSPARENT);
+        int rn = sol_enum_body(fp, bp, M_REFLECTIVE);
+        int dn = sol_enum_body(fp, bp, M_DECAL);
+
+        /* Draw all opaque geometry, decals last. */
 
-        if (sol_enum_body(fp, bp, M_OPAQUE | M_ENVIRONMENT))
+        if (on)
         {
             fp->bv[i].ol = glGenLists(1);
 
             glNewList(fp->bv[i].ol, GL_COMPILE);
             {
-                sol_draw_body(fp, fp->bv + i, M_OPAQUE | M_ENVIRONMENT);
+                const struct s_mtrl *mp = &default_mtrl;
+
+                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();
         }
         else fp->bv[i].ol = 0;
 
-        /* Draw all translucent geometry. */
+        /* Draw all translucent geometry, decals first. */
 
-        if (sol_enum_body(fp, bp, M_TRANSPARENT))
+        if (tn)
         {
             fp->bv[i].tl = glGenLists(1);
 
             glNewList(fp->bv[i].tl, GL_COMPILE);
             {
-                sol_draw_body(fp, fp->bv + i, M_TRANSPARENT);
+                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, 0);
+                mp = sol_draw_mtrl(fp, &default_mtrl, mp);
             }
             glEndList();
         }
@@ -469,13 +623,16 @@ static void sol_load_objects(struct s_file *fp, int s)
 
         /* Draw all reflective geometry. */
 
-        if (sol_enum_body(fp, bp, M_REFLECTIVE))
+        if (rn)
         {
             fp->bv[i].rl = glGenLists(1);
 
             glNewList(fp->bv[i].rl, GL_COMPILE);
             {
-                sol_draw_body(fp, fp->bv + i, M_REFLECTIVE);
+                const struct s_mtrl *mp = &default_mtrl;
+
+                mp = sol_draw_body(fp, fp->bv + i, mp, M_REFLECTIVE, 0);
+                mp = sol_draw_mtrl(fp, &default_mtrl, mp);
             }
             glEndList();
         }
@@ -483,13 +640,15 @@ static void sol_load_objects(struct s_file *fp, int s)
 
         /* Draw all shadowed geometry. */
 
-        if (s && sol_enum_body(fp, bp, M_SHADOWED))
+        if (s && (on || rn))
         {
             fp->bv[i].sl = glGenLists(1);
 
             glNewList(fp->bv[i].sl, GL_COMPILE);
             {
-                sol_shad_body(fp, fp->bv + i, M_SHADOWED);
+                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();
         }
@@ -497,73 +656,40 @@ static void sol_load_objects(struct s_file *fp, int s)
     }
 }
 
-static SDL_Surface *sol_find_texture(const char *name)
+static GLuint sol_find_texture(const char *name)
 {
     char png[MAXSTR];
-    char tga[MAXSTR];
     char jpg[MAXSTR];
-    SDL_Surface *s;
+
+    GLuint o;
 
     /* Prefer a lossless copy of the texture over a lossy compression. */
 
     strncpy(png, name, PATHMAX); strcat(png, ".png");
-    strncpy(tga, name, PATHMAX); strcat(tga, ".tga");
     strncpy(jpg, name, PATHMAX); strcat(jpg, ".jpg");
 
     /* Check for a PNG. */
 
-    if ((s = IMG_Load(config_data(png))))
-        return s;
-
-    /* Check for a TGA, swapping channels if found. */
-
-    if ((s = IMG_Load(config_data(tga))))
-    {
-        image_swab(s);
-        return s;
-    }
+    if ((o = make_image_from_file(png)))
+        return o;
 
     /* Check for a JPG. */
 
-    if ((s = IMG_Load(config_data(jpg))))
-        return s;
+    if ((o = make_image_from_file(jpg)))
+        return o;
 
-    return NULL;
+    return 0;
 }
 
-static void sol_load_textures(struct s_file *fp, int k)
+static void sol_load_textures(struct s_file *fp)
 {
-    SDL_Surface *s;
-    SDL_Surface *d;
-
     int i;
 
+    /* Load the image referenced by each material. */
+
     for (i = 0; i < fp->mc; i++)
-        if ((s = sol_find_texture(fp->mv[i].f)))
+        if ((fp->mv[i].o = sol_find_texture(_(fp->mv[i].f))))
         {
-            GLenum f = (s->format->BitsPerPixel == 32) ? GL_RGBA : GL_RGB;
-
-            glGenTextures(1, &fp->mv[i].o);
-            glBindTexture(GL_TEXTURE_2D, fp->mv[i].o);
-
-            if (k > 1)
-            {
-                /* Create a new buffer and copy the scaled image to it. */
-
-                if ((d = image_scale(s, k)))
-                {
-                    glTexImage2D(GL_TEXTURE_2D, 0, f, d->w, d->h, 0, f,
-                                 GL_UNSIGNED_BYTE, d->pixels);
-                    SDL_FreeSurface(d);
-                }
-            }
-            else
-                glTexImage2D(GL_TEXTURE_2D, 0, f, s->w, s->h, 0, f,
-                             GL_UNSIGNED_BYTE, s->pixels);
-
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
             /* Set the texture to clamp or repeat based on material type. */
 
             if (fp->mv[i].fl & M_CLAMPED)
@@ -576,18 +702,16 @@ static void sol_load_textures(struct s_file *fp, int k)
                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
             }
-
-            SDL_FreeSurface(s);
         }
 }
 
 /*---------------------------------------------------------------------------*/
 
-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;
     }