r_entity.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 1997-2001 Id Software, Inc.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "r_local.h"
00026 #include "r_matrix.h"
00027 #include "r_entity.h"
00028 #include "r_mesh.h"
00029 #include "r_mesh_anim.h"
00030 #include "r_draw.h"
00031 
00032 #define MAX_ENTITIES    2048
00033 
00034 static entity_t r_entities[MAX_ENTITIES];
00035 
00036 /* getters and setters for origin */
00037 const vec3_t *R_EntityGetOrigin(const entity_t *ent) { return &ent->origin; }
00038 void R_EntitySetOrigin(entity_t *ent, const vec3_t ovec) { VectorCopy(ovec, ent->origin); }
00039 void R_EntityCopyOrigin(entity_t *ent, const entity_t *other) { VectorCopy(other->origin, ent->origin); }
00040 void R_EntityAddToOrigin(entity_t *ent, const vec3_t offs) { VectorAdd(ent->origin, offs, ent->origin); }
00041 void R_EntitySubtractFromOrigin(entity_t *ent, const vec3_t offs) { VectorSubtract(ent->origin, offs, ent->origin); }
00042 
00048 static void R_DrawBox (const entity_t * e)
00049 {
00050     const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha};
00051 
00052     glDisable(GL_TEXTURE_2D);
00053 
00054     R_Color(color);
00055 
00056     if (VectorNotEmpty(e->mins) && VectorNotEmpty(e->maxs)) {
00057         R_DrawBoundingBox(e->mins, e->maxs);
00058     } else {
00059         vec3_t upper, lower;
00060         const float dx = e->oldorigin[0] - e->origin[0];
00061         const float dy = e->oldorigin[1] - e->origin[1];
00062 
00063         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00064 
00065         VectorCopy(e->origin, lower);
00066         VectorCopy(e->origin, upper);
00067         upper[2] = e->oldorigin[2];
00068 
00069         glLineWidth(2.0f);
00070         glBegin(GL_QUAD_STRIP);
00071         glVertex3fv(lower);
00072         glVertex3fv(upper);
00073         lower[0] += dx;
00074         upper[0] += dx;
00075         glVertex3fv(lower);
00076         glVertex3fv(upper);
00077         lower[1] += dy;
00078         upper[1] += dy;
00079         glVertex3fv(lower);
00080         glVertex3fv(upper);
00081         lower[0] -= dx;
00082         upper[0] -= dx;
00083         glVertex3fv(lower);
00084         glVertex3fv(upper);
00085         lower[1] -= dy;
00086         upper[1] -= dy;
00087         glVertex3fv(lower);
00088         glVertex3fv(upper);
00089         glEnd();
00090 
00091         glLineWidth(1.0f);
00092         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00093     }
00094 
00095     glEnable(GL_TEXTURE_2D);
00096 
00097     R_Color(NULL);
00098 }
00099 
00105 static void R_DrawFloor (const entity_t * e)
00106 {
00107     vec3_t upper, lower;
00108     float dx, dy;
00109     const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha};
00110 
00111     glDisable(GL_TEXTURE_2D);
00112     glEnable(GL_LINE_SMOOTH);
00113 
00114     R_Color(color);
00115 
00116     VectorCopy(e->origin, lower);
00117     VectorCopy(e->origin, upper);
00118 
00119     dx = PLAYER_WIDTH * 2;
00120     dy = e->oldorigin[2];
00121 
00122     upper[2] += dy;
00123 
00124     glBegin(GL_QUAD_STRIP);
00125     glVertex3fv(lower);
00126     glVertex3fv(upper);
00127     lower[0] += dx;
00128     upper[0] += dx;
00129     glVertex3fv(lower);
00130     glVertex3fv(upper);
00131     lower[1] += dx;
00132     upper[1] += dx;
00133     glVertex3fv(lower);
00134     glVertex3fv(upper);
00135     lower[0] -= dx;
00136     upper[0] -= dx;
00137     glVertex3fv(lower);
00138     glVertex3fv(upper);
00139     lower[1] -= dx;
00140     upper[1] -= dx;
00141     glVertex3fv(lower);
00142     glVertex3fv(upper);
00143     glEnd();
00144 
00145     lower[2] += dy;
00146     upper[1] += dx;
00147 
00148     glBegin(GL_QUAD_STRIP);
00149     glVertex3fv(lower);
00150     glVertex3fv(upper);
00151     lower[0] += dx;
00152     upper[0] += dx;
00153     glVertex3fv(lower);
00154     glVertex3fv(upper);
00155     glEnd();
00156     glDisable(GL_LINE_SMOOTH);
00157 
00158     glEnable(GL_TEXTURE_2D);
00159 
00160     R_Color(NULL);
00161 }
00162 
00168 static void R_DrawArrow (const entity_t * e)
00169 {
00170     vec3_t upper, mid, lower;
00171     const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha};
00172 
00173     VectorCopy(e->origin, upper);
00174     upper[0] += 2;
00175 
00176     VectorCopy(e->origin, mid);
00177     mid[1] += 2;
00178 
00179     VectorCopy(e->origin, lower);
00180     lower[2] += 2;
00181 
00182     glDisable(GL_TEXTURE_2D);
00183     glEnable(GL_LINE_SMOOTH);
00184 
00185     R_Color(color);
00186 
00187     glBegin(GL_TRIANGLE_FAN);
00188     glVertex3fv(e->oldorigin);
00189     glVertex3fv(upper);
00190     glVertex3fv(mid);
00191     glVertex3fv(lower);
00192     glEnd();
00193 
00194     glDisable(GL_LINE_SMOOTH);
00195     glEnable(GL_TEXTURE_2D);
00196 
00197     R_Color(NULL);
00198 }
00199 
00204 static void R_DrawEntityEffects (void)
00205 {
00206     int i;
00207 
00208     R_EnableBlend(qtrue);
00209 
00210     for (i = 0; i < refdef.numEntities; i++) {
00211         const entity_t *e = &r_entities[i];
00212 
00213         if (e->flags <= RF_BOX)
00214             continue;
00215 
00216         glPushMatrix();
00217         glMultMatrixf(e->transform.matrix);
00218 
00219         if (r_shadows->integer && (e->flags & (RF_SHADOW | RF_BLOOD))) {
00220             if (e->flags & RF_SHADOW) {
00221                 R_BindTexture(shadow->texnum);
00222             } else {
00223                 assert(e->deathTexture);
00224                 R_BindTexture(e->deathTexture->texnum);
00225             }
00226 
00227             glBegin(GL_QUADS);
00228             glTexCoord2f(0.0, 1.0);
00229             glVertex3f(-18.0, 14.0, -28.5);
00230             glTexCoord2f(1.0, 1.0);
00231             glVertex3f(10.0, 14.0, -28.5);
00232             glTexCoord2f(1.0, 0.0);
00233             glVertex3f(10.0, -14.0, -28.5);
00234             glTexCoord2f(0.0, 0.0);
00235             glVertex3f(-18.0, -14.0, -28.5);
00236             glEnd();
00237         }
00238 
00239         if (e->flags & (RF_SELECTED | RF_ALLIED | RF_MEMBER)) {
00240             /* draw the circles for team-members and allied troops */
00241             vec4_t color = {1, 1, 1, 1};
00242             glDisable(GL_DEPTH_TEST);
00243             glDisable(GL_TEXTURE_2D);
00244             glEnable(GL_LINE_SMOOTH);
00245 
00246             if (e->flags & RF_MEMBER) {
00247                 if (e->flags & RF_SELECTED)
00248                     Vector4Set(color, 0, 1, 0, 1);
00249                 else
00250                     Vector4Set(color, 0, 1, 0, 0.3);
00251             } else if (e->flags & RF_ALLIED)
00252                 Vector4Set(color, 0, 0.5, 1, 0.3);
00253             else
00254                 Vector4Set(color, 0, 1, 0, 1);
00255 
00256             R_Color(color);
00257 
00258             /* circle points */
00259             glBegin(GL_LINE_STRIP);
00260             glVertex3f(10.0, 0.0, -27.0);
00261             glVertex3f(7.0, -7.0, -27.0);
00262             glVertex3f(0.0, -10.0, -27.0);
00263             glVertex3f(-7.0, -7.0, -27.0);
00264             glVertex3f(-10.0, 0.0, -27.0);
00265             glVertex3f(-7.0, 7.0, -27.0);
00266             glVertex3f(0.0, 10.0, -27.0);
00267             glVertex3f(7.0, 7.0, -27.0);
00268             glVertex3f(10.0, 0.0, -27.0);
00269             glEnd();
00270 
00271             glDisable(GL_LINE_SMOOTH);
00272             glEnable(GL_TEXTURE_2D);
00273             glEnable(GL_DEPTH_TEST);
00274             R_Color(NULL);
00275         }
00276         glPopMatrix();
00277     }
00278 
00279 }
00280 
00285 static void R_DrawBspEntities (const entity_t *ents)
00286 {
00287     const entity_t *e;
00288 
00289     if (!ents)
00290         return;
00291 
00292     e = ents;
00293 
00294     while (e) {
00295         R_DrawBrushModel(e);
00296         e = e->next;
00297     }
00298 }
00299 
00303 static void R_DrawMeshEntities (entity_t *ents)
00304 {
00305     entity_t *e;
00306 
00307     e = ents;
00308 
00309     while (e) {
00310         switch (e->model->type) {
00311         case mod_alias_dpm:
00312         case mod_alias_md2:
00313         case mod_alias_md3:
00314         case mod_obj:
00315             R_DrawAliasModel(e);
00316             break;
00317         default:
00318             break;
00319         }
00320         e = e->next;
00321     }
00322 }
00323 
00327 static void R_DrawOpaqueMeshEntities (entity_t *ents)
00328 {
00329     if (!ents)
00330         return;
00331 
00332     if (!(refdef.rendererFlags & RDF_NOWORLDMODEL)) {
00333         R_EnableLighting(r_state.world_program, qtrue);
00334     }
00335     R_DrawMeshEntities(ents);
00336     if (!(refdef.rendererFlags & RDF_NOWORLDMODEL)) {
00337         R_EnableLighting(NULL, qfalse);
00338     }
00339 }
00340 
00344 static void R_DrawBlendMeshEntities (entity_t *ents)
00345 {
00346     if (!ents)
00347         return;
00348 
00349     if (!(refdef.rendererFlags & RDF_NOWORLDMODEL)) {
00350         R_EnableLighting(r_state.world_program, qtrue);
00351     }
00352     R_EnableBlend(qtrue);
00353     R_DrawMeshEntities(ents);
00354     R_EnableBlend(qfalse);
00355     if (!(refdef.rendererFlags & RDF_NOWORLDMODEL)) {
00356         R_EnableLighting(NULL, qfalse);
00357     }
00358 }
00359 
00364 static void R_DrawNullModel (const entity_t *e)
00365 {
00366     int i;
00367 
00368     R_EnableTexture(&texunit_diffuse, qfalse);
00369 
00370     glPushMatrix();
00371     glMultMatrixf(e->transform.matrix);
00372 
00373     glBegin(GL_TRIANGLE_FAN);
00374     glVertex3f(0, 0, -16);
00375     for (i = 0; i <= 4; i++)
00376         glVertex3f(16 * cos(i * (M_PI / 2)), 16 * sin(i * (M_PI / 2)), 0);
00377     glEnd();
00378 
00379     glBegin(GL_TRIANGLE_FAN);
00380     glVertex3f(0, 0, 16);
00381     for (i = 4; i >= 0; i--)
00382         glVertex3f(16 * cos(i * (M_PI / 2)), 16 * sin(i * (M_PI / 2)), 0);
00383     glEnd();
00384 
00385     glPopMatrix();
00386 
00387     R_EnableTexture(&texunit_diffuse, qtrue);
00388 }
00389 
00390 static void R_DrawSpecialEntities (const entity_t *ents)
00391 {
00392     const entity_t *e;
00393 
00394     if (!ents)
00395         return;
00396 
00397     e = ents;
00398 
00399     R_EnableBlend(qtrue);
00400 
00401     while (e) {
00402         if (e->flags & RF_BOX) {
00403             R_DrawBox(e);
00404         } else if (e->flags & RF_PATH) {
00405             R_DrawFloor(e);
00406         } else if (e->flags & RF_ARROW) {
00407             R_DrawArrow(e);
00408         }
00409         e = e->next;
00410     }
00411 
00412     R_EnableBlend(qfalse);
00413 }
00414 
00418 static void R_DrawNullEntities (const entity_t *ents)
00419 {
00420     const entity_t *e;
00421 
00422     if (!ents)
00423         return;
00424 
00425     e = ents;
00426 
00427     while (e) {
00428         R_DrawNullModel(e);
00429         e = e->next;
00430     }
00431 }
00432 
00437 static float *R_CalcTransform (entity_t * e)
00438 {
00439     transform_t *t;
00440     float *mp;
00441     float mt[16], mc[16];
00442 
00443     /* check if this entity is already transformed */
00444     t = &e->transform;
00445 
00446     if (t->processing)
00447         Com_Error(ERR_DROP, "Ring in entity transformations!");
00448 
00449     if (t->done)
00450         return t->matrix;
00451 
00452     /* process this matrix */
00453     t->processing = qtrue;
00454     mp = NULL;
00455 
00456     /* do parent object transformations first */
00457     if (e->tagent) {
00458         /* tag transformation */
00459         const float *tag = R_GetTagMatrix(e->tagent->model, e->tagname);
00460         if (tag) {
00461             const dMD2tag_t *taghdr = (const dMD2tag_t *) e->tagent->model->alias.tagdata;
00462             float interpolated[16];
00463 
00464             /* parent transformation */
00465             mp = R_CalcTransform(e->tagent);
00466 
00467             /* do interpolation */
00468             R_InterpolateTransform(&e->tagent->as, taghdr->num_frames, tag, interpolated);
00469 
00470             /* transform */
00471             GLMatrixMultiply(mp, interpolated, mt);
00472             mp = mt;
00473         }
00474     }
00475 
00476     GLMatrixAssemble(e->origin, e->angles, mc);
00477 
00478     /* combine transformations */
00479     if (mp)
00480         GLMatrixMultiply(mp, mc, t->matrix);
00481     else
00482         memcpy(t->matrix, mc, sizeof(float) * 16);
00483 
00484     /* we're done */
00485     t->done = qtrue;
00486     t->processing = qfalse;
00487 
00488     return t->matrix;
00489 }
00490 
00497 static qboolean R_CullEntity (entity_t *e)
00498 {
00499     if (refdef.rendererFlags & RDF_NOWORLDMODEL)
00500         return qfalse;
00501 
00502     if (r_nocull->integer)
00503         return qfalse;
00504 
00505     if (!e->model)  /* don't bother culling null model ents */
00506         return qfalse;
00507 
00508     if (e->model->type == mod_bsp_submodel)
00509         return R_CullBspModel(e);
00510     else
00511         return R_CullMeshModel(e);
00512 }
00513 
00514 #if 0
00515 
00524 static int R_SortEntities (const void *ent1, const void *ent2)
00525 {
00526     return ((const entity_t*)ent1)->distanceFromViewOrigin - ((const entity_t*)ent2)->distanceFromViewOrigin;
00527 }
00528 #endif
00529 
00534 void R_DrawEntities (void)
00535 {
00536     int i;
00537     entity_t **chain;
00538     entity_t *r_bsp_entities, *r_opaque_mesh_entities;
00539     entity_t *r_blend_mesh_entities, *r_null_entities;
00540     entity_t *r_special_entities;
00541 
00542     if (!r_drawentities->integer)
00543         return;
00544 
00545     r_bsp_entities = r_opaque_mesh_entities = r_special_entities =
00546         r_blend_mesh_entities = r_null_entities = NULL;
00547 
00548 #if 0
00549     qsort(r_entities, refdef.numEntities, sizeof(entity_t), R_SortEntities);
00550 #endif
00551 
00552     for (i = 0; i < refdef.numEntities; i++) {
00553         entity_t *e = &r_entities[i];
00554 
00555         /* frustum cull check */
00556         if (R_CullEntity(e))
00557             continue;
00558 
00559         R_CalcTransform(e);
00560 
00561         if (!e->model) {
00562             if (e->flags & RF_BOX || e->flags & RF_PATH || e->flags & RF_ARROW)
00563                 chain = &r_special_entities;
00564             else
00565                 chain = &r_null_entities;
00566         } else {
00567             const image_t *skin;
00568             switch (e->model->type) {
00569             case mod_bsp_submodel:
00570                 chain = &r_bsp_entities;
00571                 break;
00572             case mod_alias_dpm:
00573             case mod_alias_md2:
00574             case mod_alias_md3:
00575             case mod_obj:
00576                 skin = R_AliasModelState(e->model, &e->as.mesh, &e->as.frame, &e->as.oldframe, &e->skinnum);
00577                 if (skin == NULL || skin->texnum == 0)
00578                     Com_Error(ERR_DROP, "Model '%s' has no skin assigned", e->model->name);
00579                 if (skin->has_alpha || e->flags & RF_TRANSLUCENT)
00580                     chain = &r_blend_mesh_entities;
00581                 else
00582                     chain = &r_opaque_mesh_entities;
00583                 break;
00584             default:
00585                 Com_Error(ERR_DROP, "Unknown model type in R_DrawEntities entity chain: %i (%s)",
00586                         e->model->type, e->model->name);
00587                 break;
00588             }
00589         }
00590         e->next = *chain;
00591         *chain = e;
00592     }
00593 
00594     R_DrawBspEntities(r_bsp_entities);
00595     R_DrawOpaqueMeshEntities(r_opaque_mesh_entities);
00596     R_DrawBlendMeshEntities(r_blend_mesh_entities);
00597     R_Color(NULL);
00598     R_DrawSpecialEntities(r_special_entities);
00599     R_DrawNullEntities(r_null_entities);
00600     R_DrawEntityEffects();
00601 }
00602 
00608 entity_t *R_GetFreeEntity (void)
00609 {
00610     if (refdef.numEntities >= MAX_ENTITIES)
00611         Com_Error(ERR_DROP, "R_GetFreeEntity: MAX_ENTITIES exceeded");
00612     return &r_entities[refdef.numEntities];
00613 }
00614 
00618 entity_t *R_GetEntity (int id)
00619 {
00620     if (id < 0 || id >= refdef.numEntities)
00621         return NULL;
00622     return &r_entities[id];
00623 }
00624 
00630 int R_AddEntity (const entity_t *ent)
00631 {
00632     if (refdef.numEntities >= MAX_ENTITIES)
00633         Com_Error(ERR_DROP, "R_AddEntity: MAX_ENTITIES exceeded");
00634 
00635     /* don't add the bsp tiles from random map assemblies */
00636     if (ent->model && ent->model->type == mod_bsp)
00637         return -1;
00638 
00639     r_entities[refdef.numEntities] = *ent;
00640     r_entities[refdef.numEntities].distanceFromViewOrigin = VectorDist(ent->origin, refdef.viewOrigin);
00641 
00642     refdef.numEntities++;
00643 
00644     return refdef.numEntities - 1;
00645 }

Generated by  doxygen 1.6.2