/* 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. */ // // All sprite drawing // #include "quakedef.h" typedef struct mspriteframe_s { int width; int height; float up, down, left, right; int gl_texturenum; } mspriteframe_t; typedef struct { int numframes; float *intervals; mspriteframe_t *frames[1]; } mspritegroup_t; typedef struct { spriteframetype_t type; mspriteframe_t *frameptr; } mspriteframedesc_t; typedef struct { int type; int maxwidth; int maxheight; int numframes; float beamlength; // remove? void *cachespot; // remove? mspriteframedesc_t frames[1]; } msprite_t; char loadname[32]; model_t *loadmodel; /* =================== Mod_LoadSpriteFrame =================== */ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum) { dspriteframe_t *pinframe; mspriteframe_t *pspriteframe; int width, height, size, origin[2]; char name[64], sprite[64]; // Tomaz - TGA pinframe = (dspriteframe_t *)pin; width = LittleLong (pinframe->width); height = LittleLong (pinframe->height); size = width * height; pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname); Q_memset (pspriteframe, 0, sizeof (mspriteframe_t)); *ppframe = pspriteframe; pspriteframe->width = width; pspriteframe->height = height; origin[0] = LittleLong (pinframe->origin[0]); origin[1] = LittleLong (pinframe->origin[1]); pspriteframe->up = origin[1]; pspriteframe->down = origin[1] - height; pspriteframe->left = origin[0]; pspriteframe->right = width + origin[0]; // Tomaz - TGA Begin COM_StripExtension(loadmodel->name, sprite); sprintf (name, "%s_%i", sprite, framenum); pspriteframe->gl_texturenum = loadtextureimage (name, false, true); if (pspriteframe->gl_texturenum == 0)// did not find a matching TGA... { sprintf (name, "%s_%i", loadmodel->name, framenum); pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true, 1); } // Tomaz - TGA End return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size); } /* ================= Mod_LoadSpriteGroup ================= */ void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum) { dspritegroup_t *pingroup; mspritegroup_t *pspritegroup; int i, numframes; dspriteinterval_t *pin_intervals; float *poutintervals; void *ptemp; pingroup = (dspritegroup_t *)pin; numframes = LittleLong (pingroup->numframes); pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname); pspritegroup->numframes = numframes; *ppframe = (mspriteframe_t *)pspritegroup; pin_intervals = (dspriteinterval_t *)(pingroup + 1); poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); pspritegroup->intervals = poutintervals; for (i=0 ; iinterval); if (*poutintervals <= 0.0) Host_Error ("Mod_LoadSpriteGroup: interval<=0"); poutintervals++; pin_intervals++; } ptemp = (void *)pin_intervals; for (i=0 ; iframes[i], framenum * 100 + i); } return ptemp; } /* ================= Mod_LoadSpriteModel ================= */ void GetMFX(model_t *mod); int GetMSForName (char *name, model_t * model); void Mod_LoadSpriteModel (model_t *mod, void *buffer) { int i; int version; dsprite_t *pin; msprite_t *psprite; int numframes; int size; dspriteframetype_t *pframetype; pin = (dsprite_t *)buffer; version = LittleLong (pin->version); if (version != SPRITE_VERSION) Sys_Error ("%s has wrong version number " "(%i should be %i)", mod->name, version, SPRITE_VERSION); numframes = LittleLong (pin->numframes); size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames); psprite = Hunk_AllocName (size, loadname); mod->cache.data = psprite; psprite->type = LittleLong (pin->type); psprite->maxwidth = LittleLong (pin->width); psprite->maxheight = LittleLong (pin->height); psprite->beamlength = LittleFloat (pin->beamlength); mod->synctype = LittleLong (pin->synctype); psprite->numframes = numframes; mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2; mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2; mod->mins[2] = -psprite->maxheight/2; mod->maxs[2] = psprite->maxheight/2; // // load the frames // if (numframes < 1) Host_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes); mod->numframes = numframes; pframetype = (dspriteframetype_t *)(pin + 1); for (i=0 ; itype); psprite->frames[i].type = frametype; if (frametype == SPR_SINGLE) { pframetype = (dspriteframetype_t *) Mod_LoadSpriteFrame (pframetype + 1, &psprite->frames[i].frameptr, i); } else { pframetype = (dspriteframetype_t *) Mod_LoadSpriteGroup (pframetype + 1, &psprite->frames[i].frameptr, i); } } mod->type = mod_sprite; //Tei finishing scripts/builtins GetMFX(mod); GetMSForName(mod->name,mod);//Tei mscript //Tei finishing scripts/builtins } //Tei hud entitys void Mod_LoadHudModel (model_t *mod, void *buffer) { mod->pic = Draw_CachePic(mod->name);//Pre-load, I suspect will speedup before mod->type = mod_hud; } //Tei hud entitys /* ================ R_GetSpriteFrame ================ */ mspriteframe_t *R_GetSpriteFrame (entity_t *e) { msprite_t *psprite; mspritegroup_t *pspritegroup; mspriteframe_t *pspriteframe; int i, numframes, frame; float *pintervals, fullinterval, targettime, time; psprite = e->model->cache.data; frame = e->frame; #if 0 if ((frame >= psprite->numframes) || (frame < 0)) { Con_DPrintf ("R_DrawSprite: no such frame %d\n", frame);//move to dprint frame = 0; } #else //TELEJANO frame %= psprite->numframes;//Q2MAX! #endif //frame = &psprite->frames[e->frame];//?? if (psprite->frames[frame].type == SPR_SINGLE) { pspriteframe = psprite->frames[frame].frameptr; } else { pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; pintervals = pspritegroup->intervals; numframes = pspritegroup->numframes; fullinterval = pintervals[numframes-1]; time = cl.time + e->syncbase; // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values // are positive, so we don't have to worry about division by 0 targettime = time - ((int)(time / fullinterval)) * fullinterval; for (i=0 ; i<(numframes-1) ; i++) { if (pintervals[i] > targettime) break; } pspriteframe = pspritegroup->frames[i]; } return pspriteframe; } /* ================= R_DrawSpriteModel ================= */ int TraceFraction (vec3_t start, vec3_t end);//Tei general trace fraction void MFX_Apply( entity_t * e); void DefineFlare(vec3_t origin, int radius, int mode, int alfa) ; void R_DrawSpriteModel (entity_t *e) { vec3_t point; mspriteframe_t *frame; vec3_t forward, right, up; msprite_t *psprite; qboolean dovisible; //Tei visible2 //Tei effect if (e->model->effect) { MFX_Apply(e); } //Tei effect if ( e->model->dpxflare ) DefineFlare(e->origin,e->model->dpxflare, 0,50);//Tei dp flare //Tei spr grass support if (e->effects3 == EF3_NOGRASS) return; glDepthMask(false); // don't even bother culling, because it's just a single // polygon without a surface cache frame = R_GetSpriteFrame (e); psprite = e->model->cache.data; if (psprite->type == SPR_ORIENTED) { // bullet marks on walls AngleVectors (e->angles, forward, right, up); } else { // normal sprite VectorCopy(vup, up); VectorCopy(vright, right); } /* Dont work.. (?) if ( e->model->dpxflare ) { DefineFlare(e->origin,e->model->dpxflare, 0,50);//Tei dp flare } */ if( e->effects3 == EF3_VISIBLE2) { dovisible = TraceFraction(e->origin,r_refdef.vieworg )>0.9999; } else dovisible = false; if (e->effects3 == EF3_VISIBLE || dovisible) glDisable(GL_DEPTH_TEST); glPushMatrix(); glScalef (e->scale, e->scale, e->scale); glColor4f (1,1,1,e->alpha); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBindTexture (GL_TEXTURE_2D, frame->gl_texturenum); glBegin (GL_QUADS); glTexCoord2f (0, 1); VectorMA (e->origin, frame->down, up, point); VectorMA (point, frame->left, right, point); glVertex3fv (point); glTexCoord2f (0, 0); VectorMA (e->origin, frame->up, up, point); VectorMA (point, frame->left, right, point); glVertex3fv (point); glTexCoord2f (1, 0); VectorMA (e->origin, frame->up, up, point); VectorMA (point, frame->right, right, point); glVertex3fv (point); glTexCoord2f (1, 1); VectorMA (e->origin, frame->down, up, point); VectorMA (point, frame->right, right, point); glVertex3fv (point); glEnd (); if (e->effects3 == EF3_VISIBLE || dovisible) glEnable(GL_DEPTH_TEST); glDepthMask(true); glPopMatrix(); glColor4f (1,1,1,1); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); }