-/*
-Copyright (C) 1996-1997 Id Software, Inc.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include "quakedef.h"
-
-cvar_t r_drawdecals = {0, "r_drawdecals", "1"};
-
-static void r_decals_start(void)
-{
-}
-
-static void r_decals_shutdown(void)
-{
-}
-
-static void r_decals_newmap(void)
-{
-}
-
-void R_Decals_Init(void)
-{
- Cvar_RegisterVariable (&r_drawdecals);
-
- R_RegisterModule("R_Decals", r_decals_start, r_decals_shutdown, r_decals_newmap);
-}
-
-/*
-static int decalindexarray[2*3] =
-{
- 0, 1, 2,
- 0, 2, 3,
-};
-*/
-
-void R_DrawDecals (void)
-{
- renderdecal_t *r;
- int i, j, lightmapstep, ds, dt;
- float fscale, fr, fg, fb, dist, f, fog, ifog, fogvec[3], impact[3], v[3], org[3], dir[3], right[3], up[3], tvxyz[4][4], tvst[4][2];
- particletexture_t *tex, *texfog;
- byte *lightmap;
- msurface_t *surf;
- rdlight_t *rd;
- rmeshinfo_t m;
-
- if (!r_drawdecals.integer)
- return;
-
- fog = 0;
- ifog = 1;
-
- Mod_CheckLoaded(cl.worldmodel);
-
- // LordHavoc: this meshinfo must match up with R_Mesh_DrawDecal
- // LordHavoc: the commented out lines are hardwired behavior in R_Mesh_DrawDecal
- memset(&m, 0, sizeof(m));
- m.blendfunc1 = GL_SRC_ALPHA;
- m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
- //m.numtriangles = 2;
- //m.numverts = 4;
- //m.index = decalindexarray;
- m.vertex = &tvxyz[0][0];
- //m.vertexstep = sizeof(float[4]);
- m.tex[0] = R_GetTexture(particlefonttexture);
- m.texcoords[0] = &tvst[0][0];
- //m.texcoordstep[0] = sizeof(float[2]);
-
- for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++)
- {
- if (r->ent)
- {
- if (r->ent->visframe != r_framecount)
- continue;
-
- Mod_CheckLoaded(r->ent->model);
- if (r->ent->model->type != mod_brush)
- continue;
-
- surf = r->ent->model->surfaces + r->surface;
-
- // skip decals on surfaces that aren't visible in this frame
- if (surf->visframe != r_framecount)
- continue;
-
- softwaretransformforentity(r->ent);
- softwaretransform(r->org, org);
- softwaretransformdirection(r->dir, dir);
-
- // do not render if the view origin is behind the decal
- VectorSubtract(org, r_origin, fogvec);
- if (DotProduct(dir, fogvec) < 0)
- continue;
- }
- else
- {
- surf = cl.worldmodel->surfaces + r->surface;
-
- // skip decals on surfaces that aren't visible in this frame
- if (surf->visframe != r_framecount)
- continue;
-
- // do not render if the view origin is behind the decal
- VectorSubtract(r->org, r_origin, fogvec);
- if (DotProduct(r->dir, fogvec) < 0)
- continue;
-
- VectorCopy(r->org, org);
- VectorCopy(r->dir, dir);
- }
-
- dist = -PlaneDiff(r->org, surf->plane);
- VectorMA(r->org, dist, surf->plane->normal, impact);
-
- ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
- dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
-
- if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
- {
- // this should never happen
- continue;
- }
-
- tex = &particletexture[r->tex][0];
- VectorVectors(dir, right, up);
- VectorScale(right, r->scale, right);
- VectorScale(up, r->scale, up);
- tvxyz[0][0] = org[0] - right[0] - up[0];
- tvxyz[0][1] = org[1] - right[1] - up[1];
- tvxyz[0][2] = org[2] - right[2] - up[2];
- tvxyz[1][0] = org[0] - right[0] + up[0];
- tvxyz[1][1] = org[1] - right[1] + up[1];
- tvxyz[1][2] = org[2] - right[2] + up[2];
- tvxyz[2][0] = org[0] + right[0] + up[0];
- tvxyz[2][1] = org[1] + right[1] + up[1];
- tvxyz[2][2] = org[2] + right[2] + up[2];
- tvxyz[3][0] = org[0] + right[0] - up[0];
- tvxyz[3][1] = org[1] + right[1] - up[1];
- tvxyz[3][2] = org[2] + right[2] - up[2];
- tvst[0][0] = tex->s1;
- tvst[0][1] = tex->t1;
- tvst[1][0] = tex->s1;
- tvst[1][1] = tex->t2;
- tvst[2][0] = tex->s2;
- tvst[2][1] = tex->t2;
- tvst[3][0] = tex->s2;
- tvst[3][1] = tex->t1;
-
- // lighting
- fr = fg = fb = 0.0f;
-
- if ((lightmap = surf->samples))
- {
- if (surf->styles[0] != 255)
- {
- lightmap += ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3;
- fscale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f);
- fr += lightmap[0] * fscale;
- fg += lightmap[1] * fscale;
- fb += lightmap[2] * fscale;
- if (surf->styles[1] != 255)
- {
- lightmapstep = (((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1)) * 3;
- lightmap += lightmapstep;
- fscale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f);
- fr += lightmap[0] * fscale;
- fg += lightmap[1] * fscale;
- fb += lightmap[2] * fscale;
- if (surf->styles[2] != 255)
- {
- lightmap += lightmapstep;
- fscale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f);
- fr += lightmap[0] * fscale;
- fg += lightmap[1] * fscale;
- fb += lightmap[2] * fscale;
- if (surf->styles[3] != 255)
- {
- lightmap += lightmapstep;
- fscale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f);
- fr += lightmap[0] * fscale;
- fg += lightmap[1] * fscale;
- fb += lightmap[2] * fscale;
- }
- }
- }
- }
- }
-
- if (surf->dlightframe == r_framecount)
- {
- for (j = 0;j < r_numdlights;j++)
- {
- if (surf->dlightbits[j >> 5] & (1 << (j & 31)))
- {
- rd = &r_dlight[j];
- VectorSubtract(r->org, rd->origin, v);
- dist = DotProduct(v, v) + LIGHTOFFSET;
- if (dist < rd->cullradius2)
- {
- f = (1.0f / dist) - rd->lightsubtract;
- if (f > 0)
- {
- fr += f * rd->light[0];
- fg += f * rd->light[1];
- fb += f * rd->light[2];
- }
- }
- }
- }
- }
-
- // if the surface is transparent, render as transparent
- m.transparent = !(surf->flags & SURF_CLIPSOLID);
- m.cr = r->color[0] * fr;
- m.cg = r->color[1] * fg;
- m.cb = r->color[2] * fb;
- m.ca = r->color[3];
-
- if (fogenabled)
- {
- fog = exp(fogdensity/DotProduct(fogvec,fogvec));
- texfog = &particletexture[r->tex][1];
- if (fog >= (1.0f / 64.0f))
- {
- if (fog >= (1.0f - (1.0f / 64.0f)))
- {
- // fully fogged, just use the fog texture and render as alpha
- m.cr = fogcolor[0];
- m.cg = fogcolor[1];
- m.cb = fogcolor[2];
- m.ca = r->color[3];
- tvst[0][0] = texfog->s1;
- tvst[0][1] = texfog->t1;
- tvst[1][0] = texfog->s1;
- tvst[1][1] = texfog->t2;
- tvst[2][0] = texfog->s2;
- tvst[2][1] = texfog->t2;
- tvst[3][0] = texfog->s2;
- tvst[3][1] = texfog->t1;
- R_Mesh_DrawDecal(&m);
- }
- else
- {
- // partially fogged, darken the first pass
- ifog = 1 - fog;
- m.cr *= ifog;
- m.cg *= ifog;
- m.cb *= ifog;
- if (tex->s1 == texfog->s1 && tex->t1 == texfog->t1)
- {
- // fog texture is the same as the base, just change the color
- m.cr += fogcolor[0] * fog;
- m.cg += fogcolor[1] * fog;
- m.cb += fogcolor[2] * fog;
- R_Mesh_DrawDecal(&m);
- }
- else
- {
- // render the first pass (alpha), then do additive fog
- R_Mesh_DrawDecal(&m);
- m.blendfunc2 = GL_ONE;
- m.cr = fogcolor[0];
- m.cg = fogcolor[1];
- m.cb = fogcolor[2];
- m.ca = r->color[3] * fog;
- tvst[0][0] = texfog->s1;
- tvst[0][1] = texfog->t1;
- tvst[1][0] = texfog->s1;
- tvst[1][1] = texfog->t2;
- tvst[2][0] = texfog->s2;
- tvst[2][1] = texfog->t2;
- tvst[3][0] = texfog->s2;
- tvst[3][1] = texfog->t1;
- R_Mesh_DrawDecal(&m);
- m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
- }
- }
- }
- else
- R_Mesh_DrawDecal(&m);
- }
- else
- R_Mesh_DrawDecal(&m);
- }
-}
-
-/*
-void R_DrawDecals (void)
-{
- renderdecal_t *r;
- int i, j, lightmapstep, ds, dt;
- float fscale, fr, fg, fb, dist, f, fog, ifog, impact[3], v[3], org[3], dir[3], right[3], up[3], tv[4][5];
- particletexture_t *tex;
- byte *lightmap;
- msurface_t *surf;
- rdlight_t *rd;
- rmeshinfo_t m;
-
- if (!r_drawdecals.integer)
- return;
-
- ifog = 1;
-
- Mod_CheckLoaded(cl.worldmodel);
-
- memset(&m, 0, sizeof(m));
- m.blendfunc1 = GL_SRC_ALPHA;
- m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
- m.numtriangles = 2;
- m.numverts = 4;
- m.index = decalindexarray;
- m.vertex = &tv[0][0];
- m.vertexstep = sizeof(float[5]);
- m.tex[0] = R_GetTexture(particlefonttexture);
- m.texcoords[0] = &tv[0][3];
- m.texcoordstep[0] = sizeof(float[5]);
-
- for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++)
- {
- if (r->ent)
- {
- if (r->ent->visframe != r_framecount)
- continue;
-
- Mod_CheckLoaded(r->ent->model);
- if (r->ent->model->type != mod_brush)
- continue;
-
- surf = r->ent->model->surfaces + r->surface;
-
- // skip decals on surfaces that aren't visible in this frame
- if (surf->visframe != r_framecount)
- continue;
-
- softwaretransformforentity(r->ent);
- softwaretransform(r->org, org);
- softwaretransformdirection(r->dir, dir);
-
- // do not render if the view origin is behind the decal
- VectorSubtract(org, r_origin, v);
- if (DotProduct(dir, v) < 0)
- continue;
- }
- else
- {
- surf = cl.worldmodel->surfaces + r->surface;
-
- // skip decals on surfaces that aren't visible in this frame
- if (surf->visframe != r_framecount)
- continue;
-
- // do not render if the view origin is behind the decal
- VectorSubtract(r->org, r_origin, v);
- if (DotProduct(r->dir, v) < 0)
- continue;
-
- VectorCopy(r->org, org);
- VectorCopy(r->dir, dir);
- }
-
- dist = -PlaneDiff(r->org, surf->plane);
- VectorMA(r->org, dist, surf->plane->normal, impact);
-
- ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
- dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
-
- if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
- {
- // this should never happen
- continue;
- }
-
- if (fogenabled)
- {
- ifog = 1 - exp(fogdensity/DotProduct(v,v));
- ifog = bound(0, ifog, 1);
- }
-
- tex = &particletexture[r->tex][0];
- VectorVectors(dir, right, up);
- VectorScale(right, r->scale, right);
- VectorScale(up, r->scale, up);
- tv[0][0] = org[0] - right[0] - up[0];
- tv[0][1] = org[1] - right[1] - up[1];
- tv[0][2] = org[2] - right[2] - up[2];
- tv[0][3] = tex->s1;
- tv[0][4] = tex->t1;
- tv[1][0] = org[0] - right[0] + up[0];
- tv[1][1] = org[1] - right[1] + up[1];
- tv[1][2] = org[2] - right[2] + up[2];
- tv[1][3] = tex->s1;
- tv[1][4] = tex->t2;
- tv[2][0] = org[0] + right[0] + up[0];
- tv[2][1] = org[1] + right[1] + up[1];
- tv[2][2] = org[2] + right[2] + up[2];
- tv[2][3] = tex->s2;
- tv[2][4] = tex->t2;
- tv[3][0] = org[0] + right[0] - up[0];
- tv[3][1] = org[1] + right[1] - up[1];
- tv[3][2] = org[2] + right[2] - up[2];
- tv[3][3] = tex->s2;
- tv[3][4] = tex->t1;
-
- // lighting
- fr = fg = fb = 0.0f;
-
- if ((lightmap = surf->samples))
- {
- if (surf->styles[0] != 255)
- {
- lightmap += ((dt >> 4) * ((surf->extents[0] >> 4) + 1) + (ds >> 4)) * 3;
- fscale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f);
- fr += lightmap[0] * fscale;
- fg += lightmap[1] * fscale;
- fb += lightmap[2] * fscale;
- if (surf->styles[1] != 255)
- {
- lightmapstep = (((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1)) * 3;
- lightmap += lightmapstep;
- fscale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f);
- fr += lightmap[0] * fscale;
- fg += lightmap[1] * fscale;
- fb += lightmap[2] * fscale;
- if (surf->styles[2] != 255)
- {
- lightmap += lightmapstep;
- fscale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f);
- fr += lightmap[0] * fscale;
- fg += lightmap[1] * fscale;
- fb += lightmap[2] * fscale;
- if (surf->styles[3] != 255)
- {
- lightmap += lightmapstep;
- fscale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f);
- fr += lightmap[0] * fscale;
- fg += lightmap[1] * fscale;
- fb += lightmap[2] * fscale;
- }
- }
- }
- }
- }
-
- if (surf->dlightframe == r_framecount)
- {
- for (j = 0;j < r_numdlights;j++)
- {
- if (surf->dlightbits[j >> 5] & (1 << (j & 31)))
- {
- rd = &r_dlight[j];
- VectorSubtract(r->org, rd->origin, v);
- dist = DotProduct(v, v) + LIGHTOFFSET;
- if (dist < rd->cullradius2)
- {
- f = (1.0f / dist) - rd->lightsubtract;
- if (f > 0)
- {
- fr += f * rd->light[0];
- fg += f * rd->light[1];
- fb += f * rd->light[2];
- }
- }
- }
- }
- }
-
- // if the surface is transparent, render as transparent
- m.transparent = !(surf->flags & SURF_CLIPSOLID);
- m.cr = r->color[0] * fr;
- m.cg = r->color[1] * fg;
- m.cb = r->color[2] * fb;
- m.ca = r->color[3];
-
- if (fogenabled)
- {
- m.cr *= ifog;
- m.cg *= ifog;
- m.cb *= ifog;
- }
-
- R_Mesh_DrawDecal(&m);
- }
-
- if (!fogenabled)
- return;
-
- m.blendfunc2 = GL_ONE;
- m.cr = fogcolor[0];
- m.cg = fogcolor[1];
- m.cb = fogcolor[2];
-
- for (i = 0, r = r_refdef.decals;i < r_refdef.numdecals;i++, r++)
- {
- if (r->ent)
- {
- if (r->ent->visframe != r_framecount)
- continue;
-
- Mod_CheckLoaded(r->ent->model);
-
- surf = r->ent->model->surfaces + r->surface;
-
- // skip decals on surfaces that aren't visible in this frame
- if (surf->visframe != r_framecount)
- continue;
-
- softwaretransformforentity(r->ent);
- softwaretransform(r->org, org);
- softwaretransformdirection(r->dir, dir);
-
- // do not render if the view origin is behind the decal
- VectorSubtract(org, r_origin, v);
- if (DotProduct(dir, v) < 0)
- continue;
- }
- else
- {
- surf = cl.worldmodel->surfaces + r->surface;
-
- // skip decals on surfaces that aren't visible in this frame
- if (surf->visframe != r_framecount)
- continue;
-
- // do not render if the view origin is behind the decal
- VectorSubtract(r->org, r_origin, v);
- if (DotProduct(r->dir, v) < 0)
- continue;
-
- VectorCopy(r->org, org);
- VectorCopy(r->dir, dir);
- }
-
- fog = exp(fogdensity/DotProduct(v,v));
- fog = bound(0, fog, 1);
- m.ca = r->color[3] * fog;
-
- if (m.ca >= 0.01f)
- {
- dist = -PlaneDiff(r->org, surf->plane);
- VectorMA(r->org, dist, surf->plane->normal, impact);
-
- ds = (int) (DotProduct(impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) - surf->texturemins[0];
- dt = (int) (DotProduct(impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) - surf->texturemins[1];
-
- if (ds < 0 || dt < 0 || ds > surf->extents[0] || dt > surf->extents[1])
- {
- // this should never happen
- continue;
- }
-
- tex = &particletexture[r->tex][1];
- VectorVectors(dir, right, up);
- VectorScale(right, r->scale, right);
- VectorScale(up, r->scale, up);
- tv[0][0] = org[0] - right[0] - up[0];
- tv[0][1] = org[1] - right[1] - up[1];
- tv[0][2] = org[2] - right[2] - up[2];
- tv[0][3] = tex->s1;
- tv[0][4] = tex->t1;
- tv[1][0] = org[0] - right[0] + up[0];
- tv[1][1] = org[1] - right[1] + up[1];
- tv[1][2] = org[2] - right[2] + up[2];
- tv[1][3] = tex->s1;
- tv[1][4] = tex->t2;
- tv[2][0] = org[0] + right[0] + up[0];
- tv[2][1] = org[1] + right[1] + up[1];
- tv[2][2] = org[2] + right[2] + up[2];
- tv[2][3] = tex->s2;
- tv[2][4] = tex->t2;
- tv[3][0] = org[0] + right[0] - up[0];
- tv[3][1] = org[1] + right[1] - up[1];
- tv[3][2] = org[2] + right[2] - up[2];
- tv[3][3] = tex->s2;
- tv[3][4] = tex->t1;
-
- // if the surface is transparent, render as transparent
- m.transparent = !(surf->flags & SURF_CLIPSOLID);
- R_Mesh_DrawDecal(&m);
- }
- }
-}
-*/