cl_view.c

Go to the documentation of this file.
00001 
00006 /*
00007 All original material Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 Original file from Quake 2 v3.21: quake2-2.31/client/cl_view.c
00010 Copyright (C) 1997-2001 Id Software, Inc.
00011 
00012 This program is free software; you can redistribute it and/or
00013 modify it under the terms of the GNU General Public License
00014 as published by the Free Software Foundation; either version 2
00015 of the License, or (at your option) any later version.
00016 
00017 This program is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00020 
00021 See the GNU General Public License for more details.
00022 
00023 You should have received a copy of the GNU General Public License
00024 along with this program; if not, write to the Free Software
00025 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00026 
00027 */
00028 
00029 #include "../client.h"
00030 #include "../cl_screen.h"
00031 #include "../cl_game.h"
00032 #include "cl_particle.h"
00033 #include "cl_localentity.h"
00034 #include "cl_actor.h"
00035 #include "cl_hud.h"
00036 #include "cl_spawn.h"
00037 #include "cl_view.h"
00038 #include "../renderer/r_main.h"
00039 #include "../renderer/r_entity.h"
00040 
00041 cvar_t* cl_map_debug;
00042 static cvar_t *cl_precache;
00043 
00047 void CL_ViewLoadMedia (void)
00048 {
00049     le_t *le;
00050     int i, max;
00051 
00052     CL_ViewUpdateRenderData();
00053 
00054     if (CL_GetConfigString(CS_TILES)[0] == '\0')
00055         return;                 /* no map loaded */
00056 
00057     Com_sprintf(cls.loadingMessages, sizeof(cls.loadingMessages), _("loading %s"), _(CL_GetConfigString(CS_MAPTITLE)));
00058     cls.loadingPercent = 0;
00059 
00060     /* register models, pics, and skins */
00061     SCR_UpdateScreen();
00062     R_ModBeginLoading(CL_GetConfigString(CS_TILES), CL_GetConfigStringInteger(CS_LIGHTMAP), CL_GetConfigString(CS_POSITIONS), CL_GetConfigString(CS_NAME));
00063     CL_SpawnParseEntitystring();
00064 
00065     Com_sprintf(cls.loadingMessages, sizeof(cls.loadingMessages), _("loading models..."));
00066     cls.loadingPercent += 10.0f;
00067     SCR_UpdateScreen();
00068 
00069     LM_Register();
00070     CL_ParticleRegisterArt();
00071 
00072     for (i = 1, max = 0; i < MAX_MODELS && CL_GetConfigString(CS_MODELS + i)[0] != '\0'; i++)
00073         max++;
00074 
00075     max += csi.numODs;
00076 
00077     for (i = 1; i < MAX_MODELS && CL_GetConfigString(CS_MODELS + i)[0] != '\0'; i++) {
00078         const char *name = CL_GetConfigString(CS_MODELS + i);
00079         /* skip inline bmodels */
00080         if (name[0] != '*') {
00081             Com_sprintf(cls.loadingMessages, sizeof(cls.loadingMessages),
00082                 _("loading %s"), name);
00083         }
00084         SCR_UpdateScreen();
00085         IN_SendKeyEvents(); /* pump message loop */
00086         cl.model_draw[i] = R_RegisterModelShort(name);
00087         /* initialize clipping for bmodels */
00088         if (name[0] == '*')
00089             cl.model_clip[i] = CM_InlineModel(cl.mapTiles, name);
00090         else
00091             cl.model_clip[i] = NULL;
00092         if (!cl.model_draw[i])
00093             Com_Error(ERR_DROP, "Could not load model '%s'\n", name);
00094 
00095         cls.loadingPercent += 100.0f / (float)max;
00096     }
00097 
00098     /* update le model references */
00099     le = NULL;
00100     while ((le = LE_GetNextInUse(le))) {
00101         if (le->modelnum1) {
00102             le->model1 = cl.model_draw[le->modelnum1];
00103             if (!le->model1)
00104                 Com_Error(ERR_DROP, "No model for %i", le->modelnum1);
00105         }
00106         if (le->modelnum2) {
00107             le->model2 = cl.model_draw[le->modelnum2];
00108             if (!le->model2)
00109                 Com_Error(ERR_DROP, "No model for %i", le->modelnum2);
00110         }
00111     }
00112 
00113     cls.loadingPercent = 100.0f;
00114     SCR_UpdateScreen();
00115 
00116     /* waiting for EV_START */
00117     Com_sprintf(cls.loadingMessages, sizeof(cls.loadingMessages), _("Awaiting game start"));
00118     SCR_UpdateScreen();
00119     refdef.ready = qtrue;
00121     refdef.weather = WEATHER_NONE;
00122     refdef.fogColor[3] = 1.0;
00123     VectorSet(refdef.fogColor, 0.75, 0.75, 0.75);
00124 }
00125 
00131 static void CL_PrecacheCharacterModels (void)
00132 {
00133     teamDef_t *td;
00134     int i, j, num;
00135     char model[MAX_QPATH];
00136     const char *path;
00137     float loading = cls.loadingPercent;
00138     linkedList_t *list;
00139     const float percent = 55.0f;
00140 
00141     /* search the name */
00142     for (i = 0, td = csi.teamDef; i < csi.numTeamDefs; i++, td++)
00143         for (j = NAME_NEUTRAL; j < NAME_LAST; j++) {
00144             /* no models for this gender */
00145             if (!td->numModels[j])
00146                 continue;
00147             /* search one of the model definitions */
00148             list = td->models[j];
00149             assert(list);
00150             for (num = 0; num < td->numModels[j]; num++) {
00151                 assert(list);
00152                 path = (const char*)list->data;
00153                 list = list->next;
00154                 /* register body */
00155                 Com_sprintf(model, sizeof(model), "%s/%s", path, list->data);
00156                 if (!R_RegisterModelShort(model))
00157                     Com_Printf("Com_PrecacheCharacterModels: Could not register model %s\n", model);
00158                 list = list->next;
00159                 /* register head */
00160                 Com_sprintf(model, sizeof(model), "%s/%s", path, list->data);
00161                 if (!R_RegisterModelShort(model))
00162                     Com_Printf("Com_PrecacheCharacterModels: Could not register model %s\n", model);
00163 
00164                 /* skip skin */
00165                 list = list->next;
00166 
00167                 /* new path */
00168                 list = list->next;
00169 
00170                 cls.loadingPercent += percent / (td->numModels[j] * csi.numTeamDefs * NAME_LAST);
00171                 SCR_DrawPrecacheScreen(qtrue);
00172             }
00173         }
00174     /* some genders may not have models - ensure that we do the wanted percent step */
00175     cls.loadingPercent = loading + percent;
00176 }
00177 
00181 void CL_ViewPrecacheModels (void)
00182 {
00183     int i;
00184     float percent = 40.0f;
00185 
00186     cls.loadingPercent = 5.0f;
00187     SCR_DrawPrecacheScreen(qtrue);
00188 
00189     if (cl_precache->integer)
00190         CL_PrecacheCharacterModels(); /* 55% */
00191     else
00192         percent = 95.0f;
00193 
00194     for (i = 0; i < csi.numODs; i++) {
00195         const objDef_t *od = INVSH_GetItemByIDX(i);
00196         if (od->type[0] == '\0' || od->isDummy)
00197             continue;
00198 
00199         if (od->model[0] != '\0') {
00200             cls.modelPool[i] = R_RegisterModelShort(od->model);
00201             if (cls.modelPool[i])
00202                 Com_DPrintf(DEBUG_CLIENT, "CL_PrecacheModels: Registered object model: '%s' (%i)\n", od->model, i);
00203         }
00204         cls.loadingPercent += percent / csi.numODs;
00205         SCR_DrawPrecacheScreen(qtrue);
00206     }
00207 
00208     cls.loadingPercent = 100.0f;
00209     SCR_DrawPrecacheScreen(qtrue);
00210 
00211     /* now make sure that all the precached models are stored until we quit the game
00212      * otherwise they would be freed with every map change */
00213     R_SwitchModelMemPoolTag();
00214 
00215     SCR_DrawPrecacheScreen(qfalse);
00216 }
00217 
00223 void CL_ViewCalcFieldOfViewX (void)
00224 {
00225     if (cl_isometric->integer) {
00226         const float zoom =  3.6 * (cl.cam.zoom - cl_camzoommin->value) + 0.3 * cl_camzoommin->value;
00227         refdef.fieldOfViewX = max(min(FOV / zoom, 140.0), 1.0);
00228     } else {
00229         refdef.fieldOfViewX = max(min(FOV / cl.cam.zoom, 95.0), 55.0);
00230     }
00231 }
00232 
00236 static inline void CL_ViewCalcFieldOfViewY (const float width, const float height)
00237 {
00238     refdef.fieldOfViewY = atan(tan(refdef.fieldOfViewX * (M_PI / 360.0)) * (height / width)) * (360.0 / M_PI);
00239 }
00240 
00244 void CL_ViewUpdateRenderData (void)
00245 {
00246     VectorCopy(cl.cam.camorg, refdef.viewOrigin);
00247     VectorCopy(cl.cam.angles, refdef.viewAngles);
00248 
00249     CL_ViewCalcFieldOfViewY(viddef.viewWidth, viddef.viewHeight);
00250 
00251     /* setup refdef */
00252     refdef.time = cl.time * 0.001;
00253     refdef.worldlevel = cl_worldlevel->integer;
00254 }
00255 
00259 void CL_ViewRender (void)
00260 {
00261     refdef.brushCount = 0;
00262     refdef.aliasCount = 0;
00263 
00264     if (cls.state != ca_active)
00265         return;
00266 
00267     if (!viddef.viewWidth || !viddef.viewHeight)
00268         return;
00269 
00270     /* still loading */
00271     if (!refdef.ready)
00272         return;
00273 
00274     refdef.numEntities = 0;
00275     refdef.mapTiles = cl.mapTiles;
00276 
00277     /* tell the bsp thread to start */
00278     r_threadstate.state = THREAD_BSP;
00279     /* make sure we are really rendering the world */
00280     refdef.rendererFlags &= ~RDF_NOWORLDMODEL;
00281     /* add local models to the renderer chain */
00282     LM_AddToScene();
00283     /* add local entities to the renderer chain */
00284     LE_AddToScene();
00285     /* adds pathing data */
00286     if (cl_map_debug->integer) {
00287         if (cl_map_debug->integer & MAPDEBUG_PATHING)
00288             CL_AddPathing();
00289         /* adds floor arrows */
00290         if (cl_map_debug->integer & MAPDEBUG_CELLS)
00291             CL_DisplayFloorArrows();
00292         /* adds wall arrows */
00293         if (cl_map_debug->integer & MAPDEBUG_WALLS)
00294             CL_DisplayObstructionArrows();
00295     }
00296     /* adds target cursor */
00297     CL_AddTargeting();
00298 
00299     /* update ref def */
00300     CL_ViewUpdateRenderData();
00301 
00302     /* render the world */
00303     R_RenderFrame();
00304 }
00305 
00312 void CL_ViewCenterAtGridPosition (const pos3_t pos)
00313 {
00314     vec3_t vec;
00315 
00316     PosToVec(pos, vec);
00317     VectorCopy(vec, cl.cam.origin);
00318     Cvar_SetValue("cl_worldlevel", pos[2]);
00319 }
00320 
00321 void CL_ViewInit (void)
00322 {
00323     cl_precache = Cvar_Get("cl_precache", "1", CVAR_ARCHIVE, "Precache character models at startup - more memory usage but smaller loading times in the game");
00324 }

Generated by  doxygen 1.6.2