00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
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
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
00453 t->processing = qtrue;
00454 mp = NULL;
00455
00456
00457 if (e->tagent) {
00458
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
00465 mp = R_CalcTransform(e->tagent);
00466
00467
00468 R_InterpolateTransform(&e->tagent->as, taghdr->num_frames, tag, interpolated);
00469
00470
00471 GLMatrixMultiply(mp, interpolated, mt);
00472 mp = mt;
00473 }
00474 }
00475
00476 GLMatrixAssemble(e->origin, e->angles, mc);
00477
00478
00479 if (mp)
00480 GLMatrixMultiply(mp, mc, t->matrix);
00481 else
00482 memcpy(t->matrix, mc, sizeof(float) * 16);
00483
00484
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)
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
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
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 }