/* Copyright (C) 1997-2001 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. */ // gl_script.c - scripted texture rendering - MrG #include "gl_local.h" void CIN_FreeCin (int texnum); extern float r_turbsin[]; #define TURBSCALE (256.0 / (2 * M_PI)) #define TOK_DELIMINATORS "\r\n\t " float rs_realtime = 0; rscript_t *rs_rootscript = NULL; void setRenderDynamic (void); void RS_ListScripts (void) { rscript_t *rs; int i; for (i = 0, rs = rs_rootscript; rs; rs = rs->next, i++) ri.Con_Printf (PRINT_ALL, ">> %s\n", rs->name); } int RS_Random(rs_stage_t *stage, msurface_t *surf) { random_stage_t *randStage = stage->rand_stage; int number = 0, i; glpoly_t *poly; for (poly=surf->polys ; poly ; poly=poly->next) number += poly->center[0] + poly->center[1] + poly->center[2]; for (i=0; i<(number%stage->rand_count) && randStage; randStage = randStage->next) ; return randStage->texture->texnum; } int RS_Animate (rs_stage_t *stage) { anim_stage_t *anim = stage->last_anim; float time = rs_realtime * 1000 - (stage->last_anim_time + stage->anim_delay); while (stage->last_anim_time < rs_realtime) { anim = anim->next; if (!anim) anim = stage->anim_stage; stage->last_anim_time += stage->anim_delay; } stage->last_anim = anim; return anim->texture->texnum; } void *RS_AnimateSkin (rs_stage_t *stage) { anim_stage_t *anim = stage->last_anim; float time = rs_realtime * 1000 - (stage->last_anim_time + stage->anim_delay); while (stage->last_anim_time < rs_realtime) { anim = anim->next; if (!anim) anim = stage->anim_stage; stage->last_anim_time += stage->anim_delay; } stage->last_anim = anim; return anim->texture; } float cutDot (vec3_t vec1, vec3_t vec2) { float dot = DotProduct(vec1, vec2); if (dot>1) return 1; if (dot<-1) return -1; return dot; } void RS_ResetScript (rscript_t *rs) { rs_stage_t *stage = rs->stage, *tmp_stage; anim_stage_t *anim, *tmp_anim; random_stage_t *randStage, *tmp_rand; rs->name[0] = 0; while (stage != NULL) { if (stage->anim_count) { anim = stage->anim_stage; while (anim != NULL) { tmp_anim = anim; if (anim->texture) if (anim->texture->is_cin) CIN_FreeCin(anim->texture->texnum); anim = anim->next; free (tmp_anim); } } if (stage->rand_count) { randStage = stage->rand_stage; while (randStage != NULL) { tmp_rand = randStage; if (randStage->texture) if (randStage->texture->is_cin) CIN_FreeCin(randStage->texture->texnum); randStage = randStage->next; free (tmp_rand); } } tmp_stage = stage; stage = stage->next; free (tmp_stage); } rs->picsize.enable = false; rs->picsize.width = 0; rs->picsize.height = 0; rs->model = false; rs->mirror = false; rs->stage = NULL; rs->dontflush = false; rs->subdivide = 0; rs->warpdist = 0; rs->warpsmooth = 0; rs->warpspeed = 0; rs->ready = false; rs->glarescript.enabled = false; rs->glarescript.name[0] = 0; rs->glarescript.script = NULL; rs->glaretexture.enabled = false; rs->glaretexture.name[0] = 0; rs->glaretexture.texture = NULL; rs->glarecolor.blue = 0; rs->glarecolor.green = 0; rs->glarecolor.red = 0; rs->glarecolor.enabled = false; } void RS_ClearStage (rs_stage_t *stage) { anim_stage_t *anim = stage->anim_stage, *tmp_anim; random_stage_t *randStage = stage->rand_stage, *tmp_rand; while (anim != NULL) { tmp_anim = anim; anim = anim->next; free (tmp_anim); } while (randStage != NULL) { tmp_rand = randStage; randStage = randStage->next; free (tmp_rand); } stage->last_anim = 0; stage->last_anim_time = 0; stage->anim_count = 0; stage->anim_delay = 0; stage->anim_stage = NULL; stage->rand_count = 0; stage->rand_stage = NULL; stage->has_alpha = false; stage->alphamask = false; stage->alphafunc = 0; stage->alphashift.max = 0; stage->alphashift.min = 0; stage->alphashift.speed = 0; stage->blendfunc.blend = false; stage->blendfunc.dest = stage->blendfunc.source = 0; stage->colormap.enabled = false; stage->colormap.red = 0; stage->colormap.green = 0; stage->colormap.blue = 0; stage->scale.scaleX = 0; stage->scale.scaleY = 0; stage->scale.typeX = 0; stage->scale.typeY = 0; stage->offset.offX = 0; stage->offset.offY = 0; stage->scroll.speedX = 0; stage->scroll.speedY = 0; stage->scroll.typeX = 0; stage->scroll.typeY = 0; stage->frames.enabled = false; stage->frames.start = 0; stage->frames.end = 0; stage->rot_speed = 0; VectorClear(stage->origin); VectorClear(stage->angle); stage->texture = NULL; stage->depthhack = 0; stage->envmap = false; stage->dynamic = false; stage->detail = false; stage->lightmap = true; stage->next = NULL; } rscript_t *RS_NewScript (char *name) { rscript_t *rs; if (!rs_rootscript) { rs_rootscript = (rscript_t *)malloc(sizeof(rscript_t)); rs = rs_rootscript; } else { rs = rs_rootscript; while (rs->next != NULL) rs = rs->next; rs->next = (rscript_t *)malloc(sizeof(rscript_t)); rs = rs->next; } strncpy (rs->name, name, sizeof(rs->name)); rs->stage = NULL; rs->next = NULL; rs->dontflush = false; rs->subdivide = 0; rs->warpdist = 0.0f; rs->warpsmooth = 0.0f; rs->ready = false; rs->mirror = false; rs->model = false; rs->picsize.enable = false; rs->picsize.width = 0; rs->picsize.height = 0; rs->glaretexture.enabled = false; rs->glaretexture.name[0] = 0; rs->glaretexture.texture = NULL; rs->glarescript.enabled = false; rs->glarescript.name[0] = 0; rs->glarescript.script = NULL; rs->glarecolor.blue = 0; rs->glarecolor.green = 0; rs->glarecolor.red = 0; rs->glarecolor.enabled = false; return rs; } rs_stage_t *RS_NewStage (rscript_t *rs) { rs_stage_t *stage; if (rs->stage == NULL) { rs->stage = (rs_stage_t *)malloc(sizeof(rs_stage_t)); stage = rs->stage; } else { stage = rs->stage; while (stage->next != NULL) stage = stage->next; stage->next = (rs_stage_t *)malloc(sizeof(rs_stage_t)); stage = stage->next; } strncpy (stage->name, "***r_notexture***", sizeof(stage->name)); stage->rand_stage = NULL; stage->anim_stage = NULL; stage->next = NULL; stage->last_anim = NULL; RS_ClearStage (stage); return stage; } void RS_FreeAllScripts (void) { rscript_t *rs = rs_rootscript, *tmp_rs; while (rs != NULL) { tmp_rs = rs->next; RS_ResetScript(rs); free (rs); rs = tmp_rs; } rs_rootscript = NULL; } void RS_ReloadImageScriptLinks (void) { image_t *image; int i; for (i=0, image=gltextures ; iscript = RS_FindScript(image->bare_name); } void RS_FreeScript(rscript_t *rs) { rscript_t *tmp_rs; if (!rs) return; if (rs_rootscript == rs) { rs_rootscript = rs_rootscript->next; RS_ResetScript(rs); free (rs); return; } tmp_rs = rs_rootscript; while (tmp_rs->next != rs) tmp_rs = tmp_rs->next; tmp_rs->next = rs->next; RS_ResetScript (rs); free (rs); } void RS_FreeUnmarked (void) { rscript_t *rs = rs_rootscript, *tmp_rs; while (rs != NULL) { tmp_rs = rs->next; if (!rs->dontflush) RS_FreeScript(rs); rs = tmp_rs; } } rscript_t *RS_FindImageScript(image_t *image) { if (!image) return NULL; return image->script; return NULL; } rscript_t *RS_FindScript(char *name) { rscript_t *rs = rs_rootscript; while (rs != NULL) { if (!_stricmp(rs->name, name)) { if (rs->stage) return rs; else return NULL; } rs = rs->next; } return NULL; } void RS_ReadyScript (rscript_t *rs) { rs_stage_t *stage; anim_stage_t *anim; random_stage_t *randStage; char mode; if (!rs) return; if (rs->ready) return; mode = (rs->dontflush) ? it_pic : it_wall; stage = rs->stage; if (rs->glaretexture.enabled ) { rs->glaretexture.texture = GL_FindImage (rs->glaretexture.name, mode); if (!rs->glaretexture.texture) rs->glaretexture.enabled = false; } if (rs->glarescript.enabled) { if (_stricmp(rs->name, rs->glarescript.name)) //no recusive searches thanks { rs->glarescript.script = RS_FindScript(rs->glarescript.name); if (rs->glarescript.script) RS_ReadyScript(rs->glarescript.script); } } while (stage != NULL) { //set anim anim = stage->anim_stage; while (anim != NULL) { anim->texture = GL_FindImage (anim->name, mode); if (!anim->texture) anim->texture = r_notexture; anim = anim->next; } //set tiling randStage = stage->rand_stage; while (randStage != NULL) { randStage->texture = GL_FindImage (randStage->name, mode); if (!randStage->texture) randStage->texture = r_notexture; randStage = randStage->next; } //set name if (stage->name[0]) stage->texture = GL_FindImage (stage->name, mode); if (!stage->texture) stage->texture = r_notexture; //check alpha if (stage->blendfunc.blend) stage->has_alpha = true; else stage->has_alpha = false; stage = stage->next; } rs->ready = true; } void RS_UpdateRegistration (void) { rscript_t *rs = rs_rootscript; rs_stage_t *stage; anim_stage_t *anim; random_stage_t *randStage; int mode; while (rs != NULL) { mode = (rs->dontflush) ? it_pic : it_wall; stage = rs->stage; if (rs->glarescript.enabled) rs->glarescript.script = NULL; if (rs->glaretexture.enabled) { rs->glaretexture.texture = GL_FindImage (rs->glaretexture.name, mode); if (!rs->glaretexture.texture) rs->glaretexture.texture = r_notexture; } while (stage != NULL) { anim = stage->anim_stage; while (anim != NULL) { anim->texture = GL_FindImage(anim->name,mode); if (!anim->texture) anim->texture = r_notexture; anim = anim->next; } randStage = (random_stage_t*)stage->rand_stage; while (randStage != NULL) { randStage->texture = GL_FindImage(randStage->name,mode); if (!randStage->texture) randStage->texture = r_notexture; randStage = randStage->next; } if (stage->name[0]) { stage->texture = GL_FindImage(stage->name, mode); } if (!stage->texture) stage->texture = r_notexture; stage = stage->next; } rs = rs->next; } } int RS_BlendID (char *blend) { if (!blend[0]) return 0; if (!_stricmp (blend, "GL_ZERO")) return GL_ZERO; if (!_stricmp (blend, "GL_ONE")) return GL_ONE; if (!_stricmp (blend, "GL_DST_COLOR")) return GL_DST_COLOR; if (!_stricmp (blend, "GL_ONE_MINUS_DST_COLOR")) return GL_ONE_MINUS_DST_COLOR; if (!_stricmp (blend, "GL_SRC_ALPHA")) return GL_SRC_ALPHA; if (!_stricmp (blend, "GL_ONE_MINUS_SRC_ALPHA")) return GL_ONE_MINUS_SRC_ALPHA; if (!_stricmp (blend, "GL_DST_ALPHA")) return GL_DST_ALPHA; if (!_stricmp (blend, "GL_ONE_MINUS_DST_ALPHA")) return GL_ONE_MINUS_DST_ALPHA; if (!_stricmp (blend, "GL_SRC_ALPHA_SATURATE")) return GL_SRC_ALPHA_SATURATE; if (!_stricmp (blend, "GL_SRC_COLOR")) return GL_SRC_COLOR; if (!_stricmp (blend, "GL_ONE_MINUS_SRC_COLOR")) return GL_ONE_MINUS_SRC_COLOR; return 0; } int RS_FuncName (char *text) { if (!_stricmp (text, "static")) // static return 0; else if (!_stricmp (text, "sine")) // sine wave return 1; else if (!_stricmp (text, "cosine")) // cosine wave return 2; return 0; } /* scriptname { subdivide vertexwarp safe { map scroll blendfunc alphashift anim ... end envmap nolightmap alphamask } } */ void rs_stage_map (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); strncpy (stage->name, *token, sizeof(stage->name)); } void rs_stage_model (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); strncpy (stage->model, *token, sizeof(stage->model)); } void rs_stage_colormap (rs_stage_t *stage, char **token) { stage->colormap.enabled = true; *token = strtok (NULL, TOK_DELIMINATORS); stage->colormap.red = atoi(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->colormap.green = atoi(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->colormap.blue = atoi(*token); } void rs_stage_frames (rs_stage_t *stage, char **token) { stage->frames.enabled = true; *token = strtok (NULL, TOK_DELIMINATORS); stage->frames.speed = atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->frames.start = atoi(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->frames.end = atoi(*token); } void rs_stage_offset (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); stage->offset.offX = atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->offset.offY = atof(*token); } void rs_stage_scroll (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); stage->scroll.typeX = RS_FuncName(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->scroll.speedX = atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->scroll.typeY = RS_FuncName(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->scroll.speedY = atof(*token); } void rs_stage_blendfunc (rs_stage_t *stage, char **token) { stage->blendfunc.blend = true; *token = strtok (NULL, TOK_DELIMINATORS); if (!Q_stricmp (*token, "add")) { stage->blendfunc.source = GL_ONE; stage->blendfunc.dest = GL_ONE; } else if (!Q_stricmp (*token, "blend")) { stage->blendfunc.source = GL_SRC_ALPHA; stage->blendfunc.dest = GL_ONE_MINUS_SRC_ALPHA; } else if (!Q_stricmp (*token, "filter")) { stage->blendfunc.source = GL_ZERO; stage->blendfunc.dest = GL_SRC_COLOR; } else { stage->blendfunc.source = RS_BlendID (*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->blendfunc.dest = RS_BlendID (*token); } } void rs_stage_alphashift (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); stage->alphashift.speed = (float)atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->alphashift.min = (float)atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->alphashift.max = (float)atof(*token); } void rs_stage_random (rs_stage_t *stage, char **token) { random_stage_t *rand = (random_stage_t *)malloc(sizeof(random_stage_t)); stage->rand_stage = rand; stage->rand_count = 0; *token = strtok(NULL, TOK_DELIMINATORS); while (_stricmp (*token, "end")) { stage->rand_count++; strncpy (stage->name, *token, sizeof(stage->name)); stage->texture = NULL; *token = strtok(NULL, TOK_DELIMINATORS); if (!_stricmp (*token, "end")) { rand->next = NULL; break; } rand->next = (random_stage_t *)malloc(sizeof(random_stage_t)); rand = rand->next; } } void rs_stage_anim (rs_stage_t *stage, char **token) { anim_stage_t *anim = (anim_stage_t *)malloc(sizeof(anim_stage_t)); *token = strtok (NULL, TOK_DELIMINATORS); stage->anim_delay = (float)atof(*token); stage->anim_stage = anim; stage->last_anim = anim; *token = strtok(NULL, TOK_DELIMINATORS); while (_stricmp (*token, "end")) { stage->anim_count++; strncpy (anim->name, *token, sizeof(anim->name)); anim->texture = NULL; *token = strtok(NULL, TOK_DELIMINATORS); if (!_stricmp (*token, "end")) { anim->next = NULL; break; } anim->next = (anim_stage_t *)malloc(sizeof(anim_stage_t)); anim = anim->next; } } void rs_stage_depthhack (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); stage->depthhack = (float)atof(*token); } void rs_stage_envmap (rs_stage_t *stage, char **token) { stage->envmap = true; } void rs_stage_dynamic (rs_stage_t *stage, char **token) { stage->dynamic = true; } void rs_stage_detail (rs_stage_t *stage, char **token) { stage->detail = true; } void rs_stage_nolightmap (rs_stage_t *stage, char **token) { stage->lightmap = false; } void rs_stage_alphamask (rs_stage_t *stage, char **token) { stage->alphamask = true; } void rs_stage_rotate (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); stage->rot_speed = (float)atof(*token); } void rs_stage_origin (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); stage->origin[0] = (float)atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->origin[1] = (float)atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->origin[2] = (float)atof(*token); } void rs_stage_angle (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); stage->angle[0] = (float)atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->angle[1] = (float)atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->angle[2] = (float)atof(*token); } void rs_stage_scale (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); stage->scale.typeX = RS_FuncName(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->scale.scaleX = atof(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->scale.typeY = RS_FuncName(*token); *token = strtok (NULL, TOK_DELIMINATORS); stage->scale.scaleY = atof(*token); } void rs_stage_alphafunc (rs_stage_t *stage, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); if (!_stricmp (*token, "normal")) stage->alphafunc = ALPHAFUNC_NORMAL; else if (!_stricmp (*token, "-normal")) stage->alphafunc = -ALPHAFUNC_NORMAL; else if (!_stricmp (*token, "gloss")) stage->alphafunc = ALPHAFUNC_GLOSS; else if (!_stricmp (*token, "-gloss")) stage->alphafunc = -ALPHAFUNC_GLOSS; else if (!_stricmp (*token, "basic")) stage->alphafunc = ALPHAFUNC_BASIC; else if (!_stricmp (*token, "-basic")) stage->alphafunc = -ALPHAFUNC_BASIC; } static rs_stagekey_t rs_stagekeys[] = { { "colormap", &rs_stage_colormap }, { "map", &rs_stage_map }, { "model", &rs_stage_model }, { "scroll", &rs_stage_scroll }, { "offset", &rs_stage_offset }, { "frames", &rs_stage_frames }, { "blendfunc", &rs_stage_blendfunc }, { "alphashift", &rs_stage_alphashift }, { "rand", &rs_stage_random }, { "anim", &rs_stage_anim }, { "envmap", &rs_stage_envmap }, { "depthhack", &rs_stage_depthhack }, { "nolightmap", &rs_stage_nolightmap }, { "alphamask", &rs_stage_alphamask }, { "rotate", &rs_stage_rotate }, { "origin", &rs_stage_origin }, { "angle", &rs_stage_angle }, { "scale", &rs_stage_scale }, { "dynamic", &rs_stage_dynamic }, { "detail", &rs_stage_detail }, { "alphafunc", &rs_stage_alphafunc }, { NULL, NULL } }; static int num_stagekeys = sizeof (rs_stagekeys) / sizeof(rs_stagekeys[0]) - 1; // ===================================================== void rs_script_safe (rscript_t *rs, char **token) { rs->dontflush = true; } void rs_script_subdivide (rscript_t *rs, char **token) { int divsize, p2divsize; *token = strtok (NULL, TOK_DELIMINATORS); divsize = atoi (*token); // cap max & min subdivide sizes if (divsize > 128) divsize = 128; else if (divsize <= 8) divsize = 8; // find the next smallest valid ^2 size, if not already one for (p2divsize = 2; p2divsize <= divsize ; p2divsize <<= 1 ); p2divsize >>= 1; rs->subdivide = (char)p2divsize; } void rs_script_vertexwarp (rscript_t *rs, char **token) { *token = strtok(NULL, TOK_DELIMINATORS); rs->warpspeed = atof (*token); *token = strtok(NULL, TOK_DELIMINATORS); rs->warpdist = atof (*token); *token = strtok(NULL, TOK_DELIMINATORS); rs->warpsmooth = atof (*token); if (rs->warpsmooth < 0.001f) rs->warpsmooth = 0.001f; else if (rs->warpsmooth > 1.0f) rs->warpsmooth = 1.0f; } void rs_script_lightglare (rscript_t *rs, char **token) { *token = strtok(NULL, TOK_DELIMINATORS); rs->glarecolor.red = atoi(*token); *token = strtok(NULL, TOK_DELIMINATORS); rs->glarecolor.green = atoi(*token); *token = strtok(NULL, TOK_DELIMINATORS); rs->glarecolor.blue = atoi(*token); rs->glarecolor.enabled = true; } void rs_script_lightglarescript (rscript_t *rs, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); strncpy (rs->glarescript.name, *token, sizeof(rs->glarescript.name)); rs->glarescript.enabled = true; } void rs_script_lightglaretex (rscript_t *rs, char **token) { *token = strtok (NULL, TOK_DELIMINATORS); strncpy (rs->glaretexture.name, *token, sizeof(rs->glaretexture.name)); rs->glaretexture.enabled = true; } void rs_script_mirror (rscript_t *rs, char **token) { rs->mirror = true; } void rs_script_model (rscript_t *rs, char **token) { rs->model = true; } void rs_script_picsize (rscript_t *rs, char **token) { rs->picsize.enable = true; *token = strtok(NULL, TOK_DELIMINATORS); rs->picsize.width = atof (*token); *token = strtok(NULL, TOK_DELIMINATORS); rs->picsize.height = atof (*token); } static rs_scriptkey_t rs_scriptkeys[] = { { "safe", &rs_script_safe }, { "subdivide", &rs_script_subdivide }, { "vertexwarp", &rs_script_vertexwarp }, { "mirror", &rs_script_mirror }, { "model", &rs_script_model }, { "picsize", &rs_script_picsize }, { "glarecolor", &rs_script_lightglare }, { "glaretexture", &rs_script_lightglaretex}, { "glarescript", &rs_script_lightglarescript }, { NULL, NULL } }; static int num_scriptkeys = sizeof (rs_scriptkeys) / sizeof(rs_scriptkeys[0]) - 1; // ===================================================== void RS_LoadScript(char *script) { qboolean inscript = false, instage = false; char ignored = 0; char *token, *fbuf, *buf; rscript_t *rs = NULL; rs_stage_t *stage; unsigned char tcmod = 0; unsigned int len, i; len = ri.FS_LoadFile (script, (void **)&fbuf); if (!fbuf || len < 16) { ri.Con_Printf (PRINT_ALL, "Could not load script %s\n", script); return; } buf = (char *)malloc(len+1); memcpy (buf, fbuf, len); buf[len] = 0; ri.FS_FreeFile (fbuf); token = strtok (buf, TOK_DELIMINATORS); while (token != NULL) { if (!_stricmp (token, "/*") || !_stricmp (token, "[")) ignored++; else if (!_stricmp (token, "*/") || !_stricmp (token, "]")) ignored--; if (!_stricmp (token, "//")) { //IGNORE } else if (!inscript && !ignored) { if (!_stricmp (token, "{")) { inscript = true; } else { rs = RS_FindScript(token); if (rs) RS_FreeScript(rs); rs = RS_NewScript(token); } } else if (inscript && !ignored) { if (!_stricmp(token, "}")) { if (instage) { instage = false; } else { inscript = false; } } else if (!_stricmp(token, "{")) { if (!instage) { instage = true; stage = RS_NewStage(rs); } } else { if (instage && !ignored) { for (i = 0; i < num_stagekeys; i++) { if (!_stricmp (rs_stagekeys[i].stage, token)) { rs_stagekeys[i].func (stage, &token); break; } } } else { for (i = 0; i < num_scriptkeys; i++) { if (!_stricmp (rs_scriptkeys[i].script, token)) { rs_scriptkeys[i].func (rs, &token); break; } } } } } token = strtok (NULL, TOK_DELIMINATORS); } free(buf); } void RS_ScanPathForScripts (void) { char script[MAX_OSPATH]; char dirstring[1024], *c; int npakscripts, i; char *dir = ri.FS_Gamedir(); char *basedir = va("./%s", BASEDIRNAME); char **pakscripts; char *currentScript; void *delstuff; if (pakscripts = ri.FS_ListPak("scripts/", &npakscripts)) { for (i=0; ic_s - (int)fa->c_s; c_t = fa->c_t - (int)fa->c_t; /* *os = cost * (is - 0.5f) - sint * (it - 0.5f) + 0.5f; *ot = cost * (it - 0.5f) + sint * (is - 0.5f) + 0.5f; */ *os = cost * (is - c_s) + sint * (c_t - it) + c_s; *ot = cost * (it - c_t) + sint * (is - c_s) + c_t; } __inline void RS_RotateST2 (float *os, float *ot, float degrees) { float cost = cos(degrees), sint = sin(degrees); float is = *os, it = *ot; *os = cost * (is - 0.5) + sint * (0.5 - it) + 0.5; *ot = cost * (it - 0.5) + sint * (is - 0.5) + 0.5; } void RS_SetEnvmap (vec3_t v, float *os, float *ot) { vec3_t vert; vert[0] = v[0]*r_world_matrix[0]+v[1]*r_world_matrix[4]+v[2]*r_world_matrix[8] +r_world_matrix[12]; vert[1] = v[0]*r_world_matrix[1]+v[1]*r_world_matrix[5]+v[2]*r_world_matrix[9] +r_world_matrix[13]; vert[2] = v[0]*r_world_matrix[2]+v[1]*r_world_matrix[6]+v[2]*r_world_matrix[10]+r_world_matrix[14]; VectorNormalize (vert); *os = vert[0]; *ot = vert[1]; } void RS_ScaleTexcoords (rs_stage_t *stage, float *os, float *ot) { float txm = 0, tym = 0; // scale if (stage->scale.scaleX) { switch (stage->scale.typeX) { case 0: // static *os *= stage->scale.scaleX; break; case 1: // sine *os *= stage->scale.scaleX*sin(rs_realtime*0.05); break; case 2: // cosine *os *= stage->scale.scaleX*cos(rs_realtime*0.05); break; } } if (stage->scale.scaleY) { switch (stage->scale.typeY) { case 0: // static *ot *= stage->scale.scaleY; break; case 1: // sine *ot *= stage->scale.scaleY*sin(rs_realtime*0.05); break; case 2: // cosine *ot *= stage->scale.scaleY*cos(rs_realtime*0.05); break; } } } void RS_SetTexcoords (rs_stage_t *stage, float *os, float *ot, msurface_t *fa) { if (fa->flags & SURF_DRAWTURB) { *os *= 0.015625; //(1/64) *ot *= 0.015625; //(1/64) } *os += stage->offset.offX; *ot += stage->offset.offY; // rotate if (stage->rot_speed) { ri.Con_Printf( PRINT_DEVELOPER, "offset TCx=%f y=%f\n", *os, *ot ); RS_RotateST (os, ot, -stage->rot_speed * rs_realtime * 0.0087266388888888888888888888888889, fa); } RS_ScaleTexcoords(stage, os, ot); if (stage->rot_speed) { *os -= stage->offset.offX; *ot -= stage->offset.offY; } } void RS_SetTexcoords2D (rs_stage_t *stage, float *os, float *ot) { float txm = 0, tym = 0; *os += stage->offset.offX; *ot += stage->offset.offY; // rotate if (stage->rot_speed) RS_RotateST2 (os, ot, -stage->rot_speed * rs_realtime * 0.0087266388888888888888888888888889); // scale if (stage->scale.scaleX) { switch (stage->scale.typeX) { case 0: // static *os *= stage->scale.scaleX; break; case 1: // sine *os *= stage->scale.scaleX*sin(rs_realtime*0.05); break; case 2: // cosine *os *= stage->scale.scaleX*cos(rs_realtime*0.05); break; } } if (stage->scale.scaleY) { switch (stage->scale.typeY) { case 0: // static *ot *= stage->scale.scaleY; break; case 1: // sine *ot *= stage->scale.scaleY*sin(rs_realtime*0.05); break; case 2: // cosine *ot *= stage->scale.scaleY*cos(rs_realtime*0.05); break; } } if (stage->scroll.speedX) { switch(stage->scroll.typeX) { case 0: // static txm=rs_realtime*stage->scroll.speedX; break; case 1: // sine txm=sin(rs_realtime*stage->scroll.speedX); break; case 2: // cosine txm=cos(rs_realtime*stage->scroll.speedX); break; } } else txm=0; if (stage->scroll.speedY) { switch(stage->scroll.typeY) { case 0: // static tym=rs_realtime*stage->scroll.speedY; break; case 1: // sine tym=sin(rs_realtime*stage->scroll.speedY); break; case 2: // cosine tym=cos(rs_realtime*stage->scroll.speedY); break; } } else tym=0; *os += txm; *ot += tym; } float RS_AlphaFunc (int alphafunc, float alpha, vec3_t normal, vec3_t org) { vec3_t forward, dir; float temp; if (!abs(alphafunc)) goto endalpha; if (alphafunc == ALPHAFUNC_GLOSS) { //glossmap stuff here... } else if (alphafunc == ALPHAFUNC_NORMAL) { VectorSubtract(org, r_newrefdef.vieworg, dir); VectorNormalize(dir); alpha *= fabs(cutDot(dir, normal)); } endalpha: if (alpha<0) alpha = 0; if (alpha>1) alpha = 1; if (alphafunc<0) alpha = 1-alpha; return alpha; } float RS_AlphaFuncAlias (int alphafunc, float alpha, vec3_t normal, vec3_t org) { vec3_t forward; float oldalpha = alpha; if (!abs(alphafunc)) goto endalpha; if (alphafunc == ALPHAFUNC_GLOSS) { //glossmap stuff here... } endalpha: if (alpha<0) alpha = 0; if (alpha>1) alpha = 1; if (alphafunc<0) alpha = 1-alpha; return alpha; } image_t *R_TextureAnimation (mtexinfo_t *tex); rscript_t *surfaceScript(msurface_t *surf) { image_t *image = R_TextureAnimation( surf->texinfo ); if (image && image->script) { rscript_t *rs = image->script; RS_ReadyScript(rs); return rs; } return NULL; } qboolean lightmaptoggle; void ToggleLightmap (qboolean toggle) { if (toggle==lightmaptoggle) return; lightmaptoggle = toggle; if (toggle) { SetVertexOverbrights(false); GL_EnableMultitexture( true ); SetLightingMode (); } else { GL_EnableMultitexture( false ); SetVertexOverbrights(true); } } void RS_DrawSurface (msurface_t *surf, qboolean lightmap) { glpoly_t *p; float *v; int i, nv = surf->polys->numverts; vec3_t wv, vieworg, vectors[3]; rscript_t *rs = surfaceScript(surf); rs_stage_t *stage = rs->stage; float os, ot, alpha; float scale, time = rs_realtime * rs->warpspeed, txm, tym; qboolean depthmaskscript = stage->has_alpha; //for envmap by normals AngleVectors (r_newrefdef.viewangles, vectors[0], vectors[1], vectors[2]); if (depthmaskscript) qglDepthMask(false); if (!lightmap) SetVertexOverbrights(true); else lightmaptoggle = true; do { if (stage->detail && !rs_detail->value) continue; if (lightmap && stage->lightmap) { ToggleLightmap(true); GL_ShadeModel (GL_FLAT); if (stage->colormap.enabled) qglDisable (GL_TEXTURE_2D); else if (stage->dynamic) { if (surf->dynamic.enabled && surf->dynamic.image) GL_MBind (GL_TEXTURE0, surf->dynamic.image->texnum); else { setRenderDynamic (); GL_MBind (GL_TEXTURE0, r_dynamicimage->texnum); } } else if (stage->rand_count) GL_MBind (GL_TEXTURE0, RS_Random(stage, surf)); else if (stage->anim_count) GL_MBind (GL_TEXTURE0, RS_Animate(stage)); else GL_MBind (GL_TEXTURE0, stage->texture->texnum); } else { if (!stage->lightmap && lightmap) ToggleLightmap(false); GL_ShadeModel (GL_SMOOTH); if (stage->colormap.enabled) qglDisable (GL_TEXTURE_2D); else if (stage->dynamic) { if (surf->dynamic.enabled && surf->dynamic.image) GL_Bind (surf->dynamic.image->texnum); else { setRenderDynamic (); GL_Bind (r_dynamicimage->texnum); } } else if (stage->rand_count) GL_Bind (RS_Random(stage, surf)); else if (stage->anim_count) GL_Bind (RS_Animate(stage)); else GL_Bind (stage->texture->texnum); } if (stage->blendfunc.blend) { GL_BlendFunction(stage->blendfunc.source, stage->blendfunc.dest); GLSTATE_ENABLE_BLEND } else if (surf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66) && !stage->alphamask) { GL_BlendFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GLSTATE_ENABLE_BLEND } else { GLSTATE_DISABLE_BLEND } // sane defaults alpha = 1.0f; if (stage->alphashift.min || stage->alphashift.speed) { if (!stage->alphashift.speed && stage->alphashift.min > 0) { alpha = stage->alphashift.min; } else if (stage->alphashift.speed) { alpha = sin (rs_realtime * stage->alphashift.speed); alpha = (alpha + 1.0)*0.5f; if (alpha > stage->alphashift.max) alpha = stage->alphashift.max; if (alpha < stage->alphashift.min) alpha = stage->alphashift.min; } } if (surf->texinfo->flags & SURF_TRANS33 && surf->texinfo->flags & SURF_TRANS66) alpha *= DIV254BY255; else if (surf->texinfo->flags & SURF_TRANS33) alpha *= 0.33333; else if (surf->texinfo->flags & SURF_TRANS66) alpha *= 0.66666; if (stage->scroll.speedX) { switch (stage->scroll.typeX) { case 0: // static txm = rs_realtime*stage->scroll.speedX; break; case 1: // sine txm = sin (rs_realtime*stage->scroll.speedX); break; case 2: // cosine txm = cos (rs_realtime*stage->scroll.speedX); break; } } else txm=0; if (stage->scroll.speedY) { switch (stage->scroll.typeY) { case 0: // static tym = rs_realtime*stage->scroll.speedY; break; case 1: // sine tym = sin (rs_realtime*stage->scroll.speedY); break; case 2: // cosine tym = cos (rs_realtime*stage->scroll.speedY); break; } } else tym=0; if (surf->texinfo->flags & SURF_FLOWING) { float scroll; scroll = -64 * ( (r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0) ); if(scroll == 0.0) scroll = -64.0; txm += scroll; } qglColor4f (1, 1, 1, alpha); if (stage->alphamask) { GLSTATE_ENABLE_ALPHATEST } else { GLSTATE_DISABLE_ALPHATEST } if (rs->subdivide || surf->flags & SURF_DRAWTURB) { glpoly_t *bp; int i; for (bp = surf->polys; bp; bp = bp->next) { p = bp; qglBegin(GL_TRIANGLE_FAN); for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { if (stage->envmap) { RS_SetEnvmap (v, &os, &ot); //move by normal & position os-=DotProduct (surf->plane->normal, vectors[1] ) + (r_newrefdef.vieworg[0]-r_newrefdef.vieworg[1]+r_newrefdef.vieworg[2])*0.0025; ot+=DotProduct (surf->plane->normal, vectors[2] ) + (-r_newrefdef.vieworg[0]+r_newrefdef.vieworg[1]-r_newrefdef.vieworg[2])*0.0025; if (surf->texinfo->flags & SURF_FLOWING) txm = tym = 0; } else if (fabs(stage->depthhack)) { vec3_t vec; VectorSubtract(p->center, r_newrefdef.vieworg, vec); VectorNormalize(vec); os = v[3] + cutDot(vec, surf->texinfo->vecs[0])*stage->depthhack*0.01; ot = v[4] + cutDot(vec, surf->texinfo->vecs[1])*stage->depthhack*0.01; } else { /* if (surf->dynamic.enabled) { vec3_t org; VectorSubtract ( v, surf->center, org ); os = DotProduct ( org, surf->plane->normal ) + 0.5f; ot = DotProduct ( org, surf->plane->normal ) + 0.5f; } else*/ { os = v[3]; ot = v[4]; } } RS_SetTexcoords (stage, &os, &ot, surf); if (stage->lightmap && lightmap && !stage->colormap.enabled ) { qglMTexCoord2fSGIS(GL_TEXTURE0, os+txm, ot+tym); qglMTexCoord2fSGIS(GL_TEXTURE1, v[5], v[6]); } else { float red=255, green=255, blue=255; if (stage->lightmap && p->vertexlight) { red = p->vertexlight[i*3+0]/255.0f; green = p->vertexlight[i*3+1]/255.0f; blue = p->vertexlight[i*3+2]/255.0f; } if (stage->colormap.enabled) { red *= stage->colormap.red/255.0f; green *= stage->colormap.green/255.0f; blue *= stage->colormap.blue/255.0f; } alpha = RS_AlphaFunc(stage->alphafunc, alpha, surf->plane->normal, p->center); if (red>1)red=1; if (red<0) red = 0; if (green>1)green=1; if (green<0) green = 0; if (blue>1)blue=1; if (blue<0) blue = 0; qglColor4f (red, green, blue, alpha); if (!stage->colormap.enabled) qglTexCoord2f (os+txm, ot+tym); } if (!rs->warpsmooth) qglVertex3fv (v); else { scale = rs->warpdist * sin(v[0]*rs->warpsmooth+time)*sin(v[1]*rs->warpsmooth+time)*sin(v[2]*rs->warpsmooth+time); VectorMA (v, scale, surf->plane->normal, wv); qglVertex3fv (wv); } } qglEnd(); } } else { for (p = surf->polys; p; p = p->chain) { qglBegin (GL_TRIANGLE_FAN); for (i = 0, v = p->verts[0]; i < nv; i++, v += VERTEXSIZE) { if (stage->envmap) { RS_SetEnvmap (v, &os, &ot); //move by normal & position os-=DotProduct (surf->plane->normal, vectors[1] ) + (r_newrefdef.vieworg[0]-r_newrefdef.vieworg[1]+r_newrefdef.vieworg[2])*0.0025; ot+=DotProduct (surf->plane->normal, vectors[2] ) + (-r_newrefdef.vieworg[0]+r_newrefdef.vieworg[1]-r_newrefdef.vieworg[2])*0.0025; if (surf->texinfo->flags & SURF_FLOWING) txm = tym = 0; } else if (fabs(stage->depthhack)) { vec3_t vec; VectorSubtract(p->center, r_newrefdef.vieworg, vec); VectorNormalize(vec); os = v[3] + cutDot(vec, surf->texinfo->vecs[0])*stage->depthhack*0.01; ot = v[4] + cutDot(vec, surf->texinfo->vecs[1])*stage->depthhack*0.01; } else { os = v[3]; ot = v[4]; } RS_SetTexcoords (stage, &os, &ot, surf); if (stage->lightmap && lightmap && !stage->colormap.enabled ) { qglMTexCoord2fSGIS(GL_TEXTURE0, os+txm, ot+tym); qglMTexCoord2fSGIS(GL_TEXTURE1, v[5], v[6]); } else { float red=255, green=255, blue=255; if (stage->lightmap && p->vertexlight) { red = p->vertexlight[i*3+0]/255.0f; green = p->vertexlight[i*3+1]/255.0f; blue = p->vertexlight[i*3+2]/255.0f; } if (stage->colormap.enabled) { red *= stage->colormap.red/255.0f; green *= stage->colormap.green/255.0f; blue *= stage->colormap.blue/255.0f; } alpha = RS_AlphaFunc(stage->alphafunc, alpha, surf->plane->normal, v); if (red>1)red=1; if (red<0) red = 0; if (green>1)green=1; if (green<0) green = 0; if (blue>1)blue=1; if (blue<0) blue = 0; qglColor4f (red, green, blue, alpha); qglTexCoord2f (os+txm, ot+tym); } if (!rs->warpsmooth) qglVertex3fv (v); else { scale = rs->warpdist * sin(v[0]*rs->warpsmooth+time)*sin(v[1]*rs->warpsmooth+time)*sin(v[2]*rs->warpsmooth+time); VectorMA (v, scale, surf->plane->normal, wv); qglVertex3fv (wv); } } qglEnd (); } } qglColor4f(1,1,1,1); if (stage->colormap.enabled) qglEnable (GL_TEXTURE_2D); } while (stage = stage->next); if (!lightmap) SetVertexOverbrights(false); else ToggleLightmap(true); GLSTATE_DISABLE_BLEND GLSTATE_DISABLE_ALPHATEST GLSTATE_DISABLE_TEXGEN GL_ShadeModel (GL_SMOOTH); if (depthmaskscript) qglDepthMask(true); } //for special cases only void RS_DrawSurfaceTexture (msurface_t *surf, rscript_t *rs) { glpoly_t *p; float *v; int i, nv; vec3_t wv, vieworg, vectors[3]; rs_stage_t *stage; float os, ot, alpha; float scale, time, txm, tym; if (!rs) return; nv = surf->polys->numverts; stage = rs->stage; time = rs_realtime * rs->warpspeed; //for envmap by normals AngleVectors (r_newrefdef.viewangles, vectors[0], vectors[1], vectors[2]); SetVertexOverbrights(true); do { if (stage->detail && !rs_detail->value) continue; if (stage->colormap.enabled) qglDisable (GL_TEXTURE_2D); else if (stage->dynamic) { if (surf->dynamic.enabled && surf->dynamic.image) GL_Bind (surf->dynamic.image->texnum); else { setRenderDynamic (); GL_Bind (r_dynamicimage->texnum); } } else if (stage->rand_count) GL_Bind (RS_Random(stage, surf)); else if (stage->anim_count) GL_Bind (RS_Animate(stage)); else GL_Bind (stage->texture->texnum); if (stage->blendfunc.blend) { GL_BlendFunction(stage->blendfunc.source, stage->blendfunc.dest); GLSTATE_ENABLE_BLEND } else if (surf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66) && !stage->alphamask) { GL_BlendFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GLSTATE_ENABLE_BLEND } else { GLSTATE_DISABLE_BLEND } // sane defaults alpha = 1.0f; if (stage->alphashift.min || stage->alphashift.speed) { if (!stage->alphashift.speed && stage->alphashift.min > 0) { alpha = stage->alphashift.min; } else if (stage->alphashift.speed) { alpha = sin (rs_realtime * stage->alphashift.speed); alpha = (alpha + 1)*0.5f; if (alpha > stage->alphashift.max) alpha = stage->alphashift.max; if (alpha < stage->alphashift.min) alpha = stage->alphashift.min; } } if (stage->scroll.speedX) { switch (stage->scroll.typeX) { case 0: // static txm = rs_realtime*stage->scroll.speedX; break; case 1: // sine txm = sin (rs_realtime*stage->scroll.speedX); break; case 2: // cosine txm = cos (rs_realtime*stage->scroll.speedX); break; } } else txm=0; if (stage->scroll.speedY) { switch (stage->scroll.typeY) { case 0: // static tym = rs_realtime*stage->scroll.speedY; break; case 1: // sine tym = sin (rs_realtime*stage->scroll.speedY); break; case 2: // cosine tym = cos (rs_realtime*stage->scroll.speedY); break; } } else tym=0; qglColor4f (1, 1, 1, alpha); if (stage->alphamask) { GLSTATE_ENABLE_ALPHATEST } else { GLSTATE_DISABLE_ALPHATEST } if (rs->subdivide || surf->flags & SURF_DRAWTURB) { glpoly_t *bp; int i; for (bp = surf->polys; bp; bp = bp->next) { p = bp; qglBegin(GL_TRIANGLE_FAN); for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { if (stage->envmap) { RS_SetEnvmap (v, &os, &ot); //move by normal & position os-=DotProduct (surf->plane->normal, vectors[1] ) + (r_newrefdef.vieworg[0]-r_newrefdef.vieworg[1]+r_newrefdef.vieworg[2])*0.0025; ot+=DotProduct (surf->plane->normal, vectors[2] ) + (-r_newrefdef.vieworg[0]+r_newrefdef.vieworg[1]-r_newrefdef.vieworg[2])*0.0025; if (surf->texinfo->flags & SURF_FLOWING) txm = tym = 0; } else if (fabs(stage->depthhack)) { vec3_t vec; VectorSubtract(p->center, r_newrefdef.vieworg, vec); VectorNormalize(vec); os = v[3] + cutDot(vec, surf->texinfo->vecs[0])*stage->depthhack*0.01; ot = v[4] + cutDot(vec, surf->texinfo->vecs[1])*stage->depthhack*0.01; } else { os = v[3]; ot = v[4]; } RS_SetTexcoords (stage, &os, &ot, surf); { float red=255, green=255, blue=255; if (stage->lightmap && p->vertexlight) { red = p->vertexlight[i*3+0]/255.0f; green = p->vertexlight[i*3+1]/255.0f; blue = p->vertexlight[i*3+2]/255.0f; } if (stage->colormap.enabled) { red *= stage->colormap.red/255.0f; green *= stage->colormap.green/255.0f; blue *= stage->colormap.blue/255.0f; } alpha = RS_AlphaFunc(stage->alphafunc, alpha, surf->plane->normal, v); if (red>1)red=1; if (red<0) red = 0; if (green>1)green=1; if (green<0) green = 0; if (blue>1)blue=1; if (blue<0) blue = 0; qglColor4f (red, green, blue, alpha); qglTexCoord2f (os+txm, ot+tym); } if (!rs->warpsmooth) qglVertex3fv (v); else { scale = rs->warpdist * sin(v[0]*rs->warpsmooth+time)*sin(v[1]*rs->warpsmooth+time)*sin(v[2]*rs->warpsmooth+time); VectorMA (v, scale, surf->plane->normal, wv); qglVertex3fv (wv); } } qglEnd(); } } else { for (p = surf->polys; p; p = p->chain) { qglBegin (GL_TRIANGLE_FAN); for (i = 0, v = p->verts[0]; i < nv; i++, v += VERTEXSIZE) { if (stage->envmap) { RS_SetEnvmap (v, &os, &ot); //move by normal & position os-=DotProduct (surf->plane->normal, vectors[1] ) + (r_newrefdef.vieworg[0]-r_newrefdef.vieworg[1]+r_newrefdef.vieworg[2])*0.0025; ot+=DotProduct (surf->plane->normal, vectors[2] ) + (-r_newrefdef.vieworg[0]+r_newrefdef.vieworg[1]-r_newrefdef.vieworg[2])*0.0025; if (surf->texinfo->flags & SURF_FLOWING) txm = tym = 0; } else if (fabs(stage->depthhack)) { vec3_t vec; VectorSubtract(p->center, r_newrefdef.vieworg, vec); VectorNormalize(vec); os = v[3] + cutDot(vec, surf->texinfo->vecs[0])*stage->depthhack*0.01; ot = v[4] + cutDot(vec, surf->texinfo->vecs[1])*stage->depthhack*0.01; } else { os = v[3]; ot = v[4]; } RS_SetTexcoords (stage, &os, &ot, surf); { float red=255, green=255, blue=255; if (stage->lightmap && p->vertexlight) { red = p->vertexlight[i*3+0]/255.0f; green = p->vertexlight[i*3+1]/255.0f; blue = p->vertexlight[i*3+2]/255.0f; } if (stage->colormap.enabled) { red *= stage->colormap.red/255.0f; green *= stage->colormap.green/255.0f; blue *= stage->colormap.blue/255.0f; } alpha = RS_AlphaFunc(stage->alphafunc, alpha, surf->plane->normal, v); if (red>1)red=1; if (red<0) red = 0; if (green>1)green=1; if (green<0) green = 0; if (blue>1)blue=1; if (blue<0) blue = 0; qglColor4f (red, green, blue, alpha); qglTexCoord2f (os+txm, ot+tym); } if (!rs->warpsmooth) qglVertex3fv (v); else { scale = rs->warpdist * sin(v[0]*rs->warpsmooth+time)*sin(v[1]*rs->warpsmooth+time)*sin(v[2]*rs->warpsmooth+time); VectorMA (v, scale, surf->plane->normal, wv); qglVertex3fv (wv); } } qglEnd (); } } qglColor4f(1,1,1,1); if (stage->colormap.enabled) qglEnable (GL_TEXTURE_2D); } while (stage = stage->next); SetVertexOverbrights(false); } void RS_DrawSurfaceBlack (msurface_t *surf) { int i, nv, alpha; glpoly_t *p; float os, ot, *v; rscript_t *rs = surfaceScript(surf), *glarescript; nv = surf->polys->numverts; alpha = 255; if (surf->texinfo->flags & SURF_TRANS33) alpha *= 0.33333; else if (surf->texinfo->flags & SURF_TRANS66) alpha *= 0.66666; GLSTATE_DISABLE_ALPHATEST qglDisable (GL_TEXTURE_2D); if (alpha<255) { GL_BlendFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GLSTATE_ENABLE_BLEND } else GLSTATE_DISABLE_BLEND if (rs && (rs->glaretexture.enabled || rs->glarecolor.enabled||rs->glarescript.enabled)) SetVertexOverbrights(true); if (rs && (rs->glaretexture.enabled||rs->glarescript.enabled)) qglColor4ub(0, 0, 0, alpha); else if (rs && rs->glarecolor.enabled) qglColor4ub(rs->glarecolor.red, rs->glarecolor.green, rs->glarecolor.blue, alpha); else qglColor4ub(0, 0, 0, alpha); if (surf->flags & SURF_DRAWTURB) { glpoly_t *bp; for (bp = surf->polys; bp; bp = bp->next) { p = bp; qglBegin(GL_TRIANGLE_FAN); for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { qglTexCoord2f (v[3], v[4]); qglVertex3fv (v); } qglEnd(); } } else { for (p = surf->polys; p; p = p->chain) { qglBegin (GL_TRIANGLE_FAN); for (i = 0, v = p->verts[0]; i < nv; i++, v += VERTEXSIZE) { qglTexCoord2f (v[3], v[4]); qglVertex3fv (v); } qglEnd(); } } qglColor4ub(255, 255, 255, 255); qglEnable (GL_TEXTURE_2D); if (r_newrefdef.rdflags & RDF_MOTIONBLUR) return; if (rs && ((rs->glaretexture.enabled && rs->glaretexture.texture)||rs->glarescript.enabled)) { if (rs->glarescript.enabled) { RS_ReadyScript(rs->glarescript.script); RS_DrawSurfaceTexture (surf, rs->glarescript.script); } else { if (rs->glarecolor.enabled) qglColor4ub(rs->glarecolor.red, rs->glarecolor.green, rs->glarecolor.blue, alpha); else qglColor4ub(255, 255, 255, alpha); GLSTATE_ENABLE_BLEND GL_Bind(rs->glaretexture.texture->texnum); GL_BlendFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (surf->flags & SURF_DRAWTURB) { glpoly_t *bp; for (bp = surf->polys; bp; bp = bp->next) { p = bp; qglBegin(GL_TRIANGLE_FAN); for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { qglTexCoord2f (v[3], v[4]); qglVertex3fv (v); } qglEnd(); } } else { for (p = surf->polys; p; p = p->chain) { qglBegin (GL_TRIANGLE_FAN); for (i = 0, v = p->verts[0]; i < nv; i++, v += VERTEXSIZE) { qglTexCoord2f (v[3], v[4]); qglVertex3fv (v); } qglEnd(); } } GLSTATE_DISABLE_BLEND } } if (rs && (rs->glaretexture.enabled || rs->glarecolor.enabled || rs->glarescript.enabled)) SetVertexOverbrights(false); } rscript_t *rs_caustics; rscript_t *rs_goggles; void RS_LoadSpecialScripts (void) { rs_caustics = RS_FindScript("gfx/caustics"); rs_goggles = RS_FindScript("gfx/goggles"); } //add all specia effects here void RS_SpecialSurface (msurface_t *surf) { rscript_t *rs; //Underwater Caustics if (surf->flags & SURF_UNDERWATER) RS_DrawSurfaceTexture(surf, rs_caustics); if (r_newrefdef.rdflags & RDF_IRGOGGLES) RS_DrawSurfaceTexture(surf, rs_goggles); }