Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

aas_map.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 #include "qbsp.h"
00024 #include "l_mem.h"
00025 #include "../botlib/aasfile.h"      //aas_bbox_t
00026 #include "aas_store.h"              //AAS_MAX_BBOXES
00027 #include "aas_cfg.h"
00028 #include "../game/surfaceflags.h"
00029 
00030 #define SPAWNFLAG_NOT_EASY          0x00000100
00031 #define SPAWNFLAG_NOT_MEDIUM        0x00000200
00032 #define SPAWNFLAG_NOT_HARD          0x00000400
00033 #define SPAWNFLAG_NOT_DEATHMATCH    0x00000800
00034 #define SPAWNFLAG_NOT_COOP          0x00001000
00035 
00036 #define STATE_TOP               0
00037 #define STATE_BOTTOM            1
00038 #define STATE_UP                2
00039 #define STATE_DOWN          3
00040 
00041 #define DOOR_START_OPEN     1
00042 #define DOOR_REVERSE            2
00043 #define DOOR_CRUSHER            4
00044 #define DOOR_NOMONSTER      8
00045 #define DOOR_TOGGLE         32
00046 #define DOOR_X_AXIS         64
00047 #define DOOR_Y_AXIS         128
00048 
00049 #define BBOX_NORMAL_EPSILON         0.0001
00050 
00051 //===========================================================================
00052 //
00053 // Parameter:           -
00054 // Returns:             -
00055 // Changes Globals:     -
00056 //===========================================================================
00057 vec_t BoxOriginDistanceFromPlane(vec3_t normal, vec3_t mins, vec3_t maxs, int side)
00058 {
00059     vec3_t v1, v2;
00060     int i;
00061 
00062     if (side)
00063     {
00064         for (i = 0; i < 3; i++)
00065         {
00066             if (normal[i] > BBOX_NORMAL_EPSILON) v1[i] = maxs[i];
00067             else if (normal[i] < -BBOX_NORMAL_EPSILON) v1[i] = mins[i];
00068             else v1[i] = 0;
00069         } //end for
00070     } //end if
00071     else
00072     {
00073         for (i = 0; i < 3; i++)
00074         {
00075             if (normal[i] > BBOX_NORMAL_EPSILON) v1[i] = mins[i];
00076             else if (normal[i] < -BBOX_NORMAL_EPSILON) v1[i] = maxs[i];
00077             else v1[i] = 0;
00078         } //end for
00079     } //end else
00080     VectorCopy(normal, v2);
00081     VectorInverse(v2);
00082     return DotProduct(v1, v2);
00083 } //end of the function BoxOriginDistanceFromPlane
00084 //===========================================================================
00085 //
00086 // Parameter:           -
00087 // Returns:             -
00088 // Changes Globals:     -
00089 //===========================================================================
00090 vec_t CapsuleOriginDistanceFromPlane(vec3_t normal, vec3_t mins, vec3_t maxs)
00091 {
00092     float offset_up, offset_down, width, radius;
00093 
00094     width = maxs[0] - mins[0];
00095     // if the box is less high then it is wide
00096     if (maxs[2] - mins[2] < width) {
00097         width = maxs[2] - mins[2];
00098     }
00099     radius = width * 0.5;
00100     // offset to upper and lower sphere
00101     offset_up = maxs[2] - radius;
00102     offset_down = -mins[2] - radius;
00103 
00104     // if normal points upward
00105     if ( normal[2] > 0 ) {
00106         // touches lower sphere first
00107         return normal[2] * offset_down + radius;
00108     }
00109     else {
00110         // touched upper sphere first
00111         return -normal[2] * offset_up + radius;
00112     }
00113 }
00114 //===========================================================================
00115 //
00116 // Parameter:               -
00117 // Returns:                 -
00118 // Changes Globals:     -
00119 //===========================================================================
00120 void AAS_ExpandMapBrush(mapbrush_t *brush, vec3_t mins, vec3_t maxs)
00121 {
00122     int sn;
00123     float dist;
00124     side_t *s;
00125     plane_t *plane;
00126 
00127     for (sn = 0; sn < brush->numsides; sn++)
00128     {
00129         s = brush->original_sides + sn;
00130         plane = &mapplanes[s->planenum];
00131         dist = plane->dist;
00132         if (capsule_collision) {
00133             dist += CapsuleOriginDistanceFromPlane(plane->normal, mins, maxs);
00134         }
00135         else {
00136             dist += BoxOriginDistanceFromPlane(plane->normal, mins, maxs, 0);
00137         }
00138         s->planenum = FindFloatPlane(plane->normal, dist);
00139         //the side isn't a bevel after expanding
00140         s->flags &= ~SFL_BEVEL;
00141         //don't skip the surface
00142         s->surf &= ~SURF_SKIP;
00143         //make sure the texinfo is not TEXINFO_NODE
00144         //when player clip contents brushes are read from the bsp tree
00145         //they have the texinfo field set to TEXINFO_NODE
00146         //s->texinfo = 0;
00147     } //end for
00148 } //end of the function AAS_ExpandMapBrush
00149 //===========================================================================
00150 //
00151 // Parameter:               -
00152 // Returns:                 -
00153 // Changes Globals:     -
00154 //===========================================================================
00155 void AAS_SetTexinfo(mapbrush_t *brush)
00156 {
00157     int n;
00158     side_t *side;
00159 
00160     if (brush->contents & (CONTENTS_LADDER
00161                                     | CONTENTS_AREAPORTAL
00162                                     | CONTENTS_CLUSTERPORTAL
00163                                     | CONTENTS_TELEPORTER
00164                                     | CONTENTS_JUMPPAD
00165                                     | CONTENTS_DONOTENTER
00166                                     | CONTENTS_WATER
00167                                     | CONTENTS_LAVA
00168                                     | CONTENTS_SLIME
00169                                     | CONTENTS_WINDOW
00170                                     | CONTENTS_PLAYERCLIP))
00171     {
00172         //we just set texinfo to 0 because these brush sides MUST be used as
00173         //bsp splitters textured or not textured
00174         for (n = 0; n < brush->numsides; n++)
00175         {
00176             side = brush->original_sides + n;
00177             //side->flags |= SFL_TEXTURED|SFL_VISIBLE;
00178             side->texinfo = 0;
00179         } //end for
00180     } //end if
00181     else
00182     {
00183         //only use brush sides as splitters if they are textured
00184         //texinfo of non-textured sides will be set to TEXINFO_NODE
00185         for (n = 0; n < brush->numsides; n++)
00186         {
00187             side = brush->original_sides + n;
00188             //don't use side as splitter (set texinfo to TEXINFO_NODE) if not textured
00189             if (side->flags & (SFL_TEXTURED|SFL_BEVEL)) side->texinfo = 0;
00190             else side->texinfo = TEXINFO_NODE;
00191         } //end for
00192     } //end else
00193 } //end of the function AAS_SetTexinfo
00194 //===========================================================================
00195 //
00196 // Parameter:               -
00197 // Returns:                 -
00198 // Changes Globals:     -
00199 //===========================================================================
00200 void FreeBrushWindings(mapbrush_t *brush)
00201 {
00202     int n;
00203     side_t *side;
00204     //
00205     for (n = 0; n < brush->numsides; n++)
00206     {
00207         side = brush->original_sides + n;
00208         //
00209         if (side->winding) FreeWinding(side->winding);
00210     } //end for
00211 } //end of the function FreeBrushWindings
00212 //===========================================================================
00213 //
00214 // Parameter:               -
00215 // Returns:                 -
00216 // Changes Globals:     -
00217 //===========================================================================
00218 void AAS_AddMapBrushSide(mapbrush_t *brush, int planenum)
00219 {
00220     side_t *side;
00221     //
00222     if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
00223         Error ("MAX_MAPFILE_BRUSHSIDES");
00224     //
00225     side = brush->original_sides + brush->numsides;
00226     side->original = NULL;
00227     side->winding = NULL;
00228     side->contents = brush->contents;
00229     side->flags &= ~(SFL_BEVEL|SFL_VISIBLE);
00230     side->surf = 0;
00231     side->planenum = planenum;
00232     side->texinfo = 0;
00233     //
00234     nummapbrushsides++;
00235     brush->numsides++;
00236 } //end of the function AAS_AddMapBrushSide
00237 //===========================================================================
00238 //
00239 // Parameter:               -
00240 // Returns:                 -
00241 // Changes Globals:     -
00242 //===========================================================================
00243 void AAS_FixMapBrush(mapbrush_t *brush)
00244 {
00245     int i, j, planenum;
00246     float dist;
00247     winding_t *w;
00248     plane_t *plane, *plane1, *plane2;
00249     side_t *side;
00250     vec3_t normal;
00251 
00252     //calculate the brush bounds
00253     ClearBounds(brush->mins, brush->maxs);
00254     for (i = 0; i < brush->numsides; i++)
00255     {
00256         plane = &mapplanes[brush->original_sides[i].planenum];
00257         w = BaseWindingForPlane(plane->normal, plane->dist);
00258         for (j = 0; j < brush->numsides && w; j++)
00259         {
00260             if (i == j) continue;
00261             //there are no brush bevels marked but who cares :)
00262             if (brush->original_sides[j].flags & SFL_BEVEL) continue;
00263             plane = &mapplanes[brush->original_sides[j].planenum^1];
00264             ChopWindingInPlace(&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
00265         } //end for
00266 
00267         side = &brush->original_sides[i];
00268         side->winding = w;
00269         if (w)
00270         {
00271             for (j = 0; j < w->numpoints; j++)
00272             {
00273                 AddPointToBounds(w->p[j], brush->mins, brush->maxs);
00274             } //end for
00275         } //end if
00276     } //end for
00277     //
00278     for (i = 0; i < brush->numsides; i++)
00279     {
00280         for (j = 0; j < brush->numsides; j++)
00281         {
00282             if (i == j) continue;
00283             plane1 = &mapplanes[brush->original_sides[i].planenum];
00284             plane2 = &mapplanes[brush->original_sides[j].planenum];
00285             if (WindingsNonConvex(brush->original_sides[i].winding,
00286                                     brush->original_sides[j].winding,
00287                                     plane1->normal, plane2->normal,
00288                                     plane1->dist, plane2->dist))
00289             {
00290                 Log_Print("non convex brush");
00291             } //end if
00292         } //end for
00293     } //end for
00294 
00295     //NOW close the fucking brush!!
00296     for (i = 0; i < 3; i++)
00297     {
00298         if (brush->mins[i] < -MAX_MAP_BOUNDS)
00299         {
00300             VectorClear(normal);
00301             normal[i] = -1;
00302             dist = MAX_MAP_BOUNDS - 10;
00303             planenum = FindFloatPlane(normal, dist);
00304             //
00305             Log_Print("mins out of range: added extra brush side\n");
00306             AAS_AddMapBrushSide(brush, planenum);
00307         } //end if
00308         if (brush->maxs[i] > MAX_MAP_BOUNDS)
00309         {
00310             VectorClear(normal);
00311             normal[i] = 1;
00312             dist = MAX_MAP_BOUNDS - 10;
00313             planenum = FindFloatPlane(normal, dist);
00314             //
00315             Log_Print("maxs out of range: added extra brush side\n");
00316             AAS_AddMapBrushSide(brush, planenum);
00317         } //end if
00318         if (brush->mins[i] > MAX_MAP_BOUNDS || brush->maxs[i] < -MAX_MAP_BOUNDS)
00319         {
00320             Log_Print("entity %i, brush %i: no visible sides on brush\n", brush->entitynum, brush->brushnum);
00321         } //end if
00322     } //end for
00323     //free all the windings
00324     FreeBrushWindings(brush);
00325 } //end of the function AAS_FixMapBrush
00326 //===========================================================================
00327 //
00328 // Parameter:               -
00329 // Returns:                 -
00330 // Changes Globals:     -
00331 //===========================================================================
00332 qboolean AAS_MakeBrushWindings(mapbrush_t *ob)
00333 {
00334     int         i, j;
00335     winding_t   *w;
00336     side_t      *side;
00337     plane_t     *plane, *plane1, *plane2;
00338 
00339     ClearBounds (ob->mins, ob->maxs);
00340 
00341     for (i = 0; i < ob->numsides; i++)
00342     {
00343         plane = &mapplanes[ob->original_sides[i].planenum];
00344         w = BaseWindingForPlane(plane->normal, plane->dist);
00345         for (j = 0; j <ob->numsides && w; j++)
00346         {
00347             if (i == j) continue;
00348             if (ob->original_sides[j].flags & SFL_BEVEL) continue;
00349             plane = &mapplanes[ob->original_sides[j].planenum^1];
00350             ChopWindingInPlace(&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
00351         }
00352 
00353         side = &ob->original_sides[i];
00354         side->winding = w;
00355         if (w)
00356         {
00357             side->flags |= SFL_VISIBLE;
00358             for (j = 0; j < w->numpoints; j++)
00359                 AddPointToBounds (w->p[j], ob->mins, ob->maxs);
00360         }
00361     }
00362     //check if the brush is convex
00363     for (i = 0; i < ob->numsides; i++)
00364     {
00365         for (j = 0; j < ob->numsides; j++)
00366         {
00367             if (i == j) continue;
00368             plane1 = &mapplanes[ob->original_sides[i].planenum];
00369             plane2 = &mapplanes[ob->original_sides[j].planenum];
00370             if (WindingsNonConvex(ob->original_sides[i].winding,
00371                                     ob->original_sides[j].winding,
00372                                     plane1->normal, plane2->normal,
00373                                     plane1->dist, plane2->dist))
00374             {
00375                 Log_Print("non convex brush");
00376             } //end if
00377         } //end for
00378     } //end for
00379     //check for out of bound brushes
00380     for (i = 0; i < 3; i++)
00381     {
00382         //IDBUG: all the indexes into the mins and maxs were zero (not using i)
00383         if (ob->mins[i] < -MAX_MAP_BOUNDS || ob->maxs[i] > MAX_MAP_BOUNDS)
00384         {
00385             Log_Print("entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum);
00386             Log_Print("ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, ob->mins[i], i, ob->maxs[i]);
00387             ob->numsides = 0; //remove the brush
00388             break;
00389         } //end if
00390         if (ob->mins[i] > MAX_MAP_BOUNDS || ob->maxs[i] < -MAX_MAP_BOUNDS)
00391         {
00392             Log_Print("entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum);
00393             Log_Print("ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, ob->mins[i], i, ob->maxs[i]);
00394             ob->numsides = 0; //remove the brush
00395             break;
00396         } //end if
00397     } //end for
00398     return true;
00399 } //end of the function AAS_MakeBrushWindings
00400 //===========================================================================
00401 //
00402 // Parameter:               -
00403 // Returns:                 -
00404 // Changes Globals:     -
00405 //===========================================================================
00406 mapbrush_t *AAS_CopyMapBrush(mapbrush_t *brush, entity_t *mapent)
00407 {
00408     int n;
00409     mapbrush_t *newbrush;
00410     side_t *side, *newside;
00411 
00412     if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
00413         Error ("MAX_MAPFILE_BRUSHES");
00414 
00415     newbrush = &mapbrushes[nummapbrushes];
00416     newbrush->original_sides = &brushsides[nummapbrushsides];
00417     newbrush->entitynum = brush->entitynum;
00418     newbrush->brushnum = nummapbrushes - mapent->firstbrush;
00419     newbrush->numsides = brush->numsides;
00420     newbrush->contents = brush->contents;
00421 
00422     //copy the sides
00423     for (n = 0; n < brush->numsides; n++)
00424     {
00425         if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
00426             Error ("MAX_MAPFILE_BRUSHSIDES");
00427         side = brush->original_sides + n;
00428 
00429         newside = newbrush->original_sides + n;
00430         newside->original = NULL;
00431         newside->winding = NULL;
00432         newside->contents = side->contents;
00433         newside->flags = side->flags;
00434         newside->surf = side->surf;
00435         newside->planenum = side->planenum;
00436         newside->texinfo = side->texinfo;
00437         nummapbrushsides++;
00438     } //end for
00439     //
00440     nummapbrushes++;
00441     mapent->numbrushes++;
00442     return newbrush;
00443 } //end of the function AAS_CopyMapBrush
00444 //===========================================================================
00445 //
00446 // Parameter:               -
00447 // Returns:                 -
00448 // Changes Globals:     -
00449 //===========================================================================
00450 int mark_entities[MAX_MAP_ENTITIES];
00451 
00452 int AAS_AlwaysTriggered_r(char *targetname)
00453 {
00454     int i;
00455 
00456     if (!strlen(targetname)) {
00457         return false;
00458     }
00459     //
00460     for (i = 0; i < num_entities; i++) {
00461         // if the entity will activate the given targetname
00462         if ( !strcmp(targetname, ValueForKey(&entities[i], "target")) ) {
00463             // if this activator is present in deathmatch
00464             if (!(atoi(ValueForKey(&entities[i], "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH)) {
00465                 // if it is a trigger_always entity
00466                 if (!strcmp("trigger_always", ValueForKey(&entities[i], "classname"))) {
00467                     return true;
00468                 }
00469                 // check for possible trigger_always entities activating this entity
00470                 if ( mark_entities[i] ) {
00471                     Warning( "entity %d, classname %s has recursive targetname %s\n", i,
00472                                         ValueForKey(&entities[i], "classname"), targetname );
00473                     return false;
00474                 }
00475                 mark_entities[i] = true;
00476                 if ( AAS_AlwaysTriggered_r(ValueForKey(&entities[i], "targetname")) ) {
00477                     return true;
00478                 }
00479             }
00480         }
00481     }
00482     return false;
00483 }
00484 
00485 int AAS_AlwaysTriggered(char *targetname) {
00486     memset( mark_entities, 0, sizeof(mark_entities) );
00487     return AAS_AlwaysTriggered_r( targetname );
00488 }
00489 //===========================================================================
00490 //
00491 // Parameter:               -
00492 // Returns:                 -
00493 // Changes Globals:     -
00494 //===========================================================================
00495 int AAS_ValidEntity(entity_t *mapent)
00496 {
00497     int i;
00498     char target[1024];
00499 
00500     //all world brushes are used for AAS
00501     if (mapent == &entities[0])
00502     {
00503         return true;
00504     } //end if
00505     //some of the func_wall brushes are also used for AAS
00506     else if (!strcmp("func_wall", ValueForKey(mapent, "classname")))
00507     {
00508         //Log_Print("found func_wall entity %d\n", mapent - entities);
00509         //if the func wall is used in deathmatch
00510         if (!(atoi(ValueForKey(mapent, "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH))
00511         {
00512             //Log_Print("func_wall USED in deathmatch mode %d\n", atoi(ValueForKey(mapent, "spawnflags")));
00513             return true;
00514         } //end if
00515     } //end else if
00516     else if (!strcmp("func_door_rotating", ValueForKey(mapent, "classname")))
00517     {
00518         //if the func_door_rotating is present in deathmatch
00519         if (!(atoi(ValueForKey(mapent, "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH))
00520         {
00521             //if the func_door_rotating is always activated in deathmatch
00522             if (AAS_AlwaysTriggered(ValueForKey(mapent, "targetname")))
00523             {
00524                 //Log_Print("found func_door_rotating in deathmatch\ntargetname %s\n", ValueForKey(mapent, "targetname"));
00525                 return true;
00526             } //end if
00527         } //end if
00528     } //end else if
00529     else if (!strcmp("trigger_hurt", ValueForKey(mapent, "classname")))
00530     {
00531         //"dmg" is the damage, for instance: "dmg" "666"
00532         return true;
00533     } //end else if
00534     else if (!strcmp("trigger_push", ValueForKey(mapent, "classname")))
00535     {
00536         return true;
00537     } //end else if
00538     else if (!strcmp("trigger_multiple", ValueForKey(mapent, "classname")))
00539     {
00540         //find out if the trigger_multiple is pointing to a target_teleporter
00541         strcpy(target, ValueForKey(mapent, "target"));
00542         for (i = 0; i < num_entities; i++)
00543         {
00544             //if the entity will activate the given targetname
00545             if (!strcmp(target, ValueForKey(&entities[i], "targetname")))
00546             {
00547                 if (!strcmp("target_teleporter", ValueForKey(&entities[i], "classname")))
00548                 {
00549                     return true;
00550                 } //end if
00551             } //end if
00552         } //end for
00553     } //end else if
00554     else if (!strcmp("trigger_teleport", ValueForKey(mapent, "classname")))
00555     {
00556         return true;
00557     } //end else if
00558     else if (!strcmp("func_static", ValueForKey(mapent, "classname")))
00559     {
00560         //FIXME: easy/medium/hard/deathmatch specific?
00561         return true;
00562     } //end else if
00563     else if (!strcmp("func_door", ValueForKey(mapent, "classname")))
00564     {
00565         return true;
00566     } //end else if
00567     return false;
00568 } //end of the function AAS_ValidEntity
00569 //===========================================================================
00570 //
00571 // Parameter:               -
00572 // Returns:                 -
00573 // Changes Globals:     -
00574 //===========================================================================
00575 int AAS_TransformPlane(int planenum, vec3_t origin, vec3_t angles)
00576 {
00577     float newdist, matrix[3][3];
00578     vec3_t normal;
00579 
00580     //rotate the node plane
00581     VectorCopy(mapplanes[planenum].normal, normal);
00582     CreateRotationMatrix(angles, matrix);
00583     RotatePoint(normal, matrix);
00584     newdist = mapplanes[planenum].dist + DotProduct(normal, origin);
00585     return FindFloatPlane(normal, newdist);
00586 } //end of the function AAS_TransformPlane
00587 //===========================================================================
00588 // this function sets the func_rotating_door in it's final position
00589 //
00590 // Parameter:               -
00591 // Returns:                 -
00592 // Changes Globals:     -
00593 //===========================================================================
00594 void AAS_PositionFuncRotatingBrush(entity_t *mapent, mapbrush_t *brush)
00595 {
00596     int spawnflags, i;
00597     float distance;
00598     vec3_t movedir, angles, pos1, pos2;
00599     side_t *s;
00600 
00601     spawnflags = FloatForKey(mapent, "spawnflags");
00602     VectorClear(movedir);
00603     if (spawnflags & DOOR_X_AXIS)
00604         movedir[2] = 1.0;       //roll
00605     else if (spawnflags & DOOR_Y_AXIS)
00606         movedir[0] = 1.0;       //pitch
00607     else // Z_AXIS
00608         movedir[1] = 1.0;       //yaw
00609 
00610     // check for reverse rotation
00611     if (spawnflags & DOOR_REVERSE)
00612         VectorInverse(movedir);
00613 
00614     distance = FloatForKey(mapent, "distance");
00615     if (!distance) distance = 90;
00616 
00617     GetVectorForKey(mapent, "angles", angles);
00618     VectorCopy(angles, pos1);
00619     VectorMA(angles, -distance, movedir, pos2);
00620     // if it starts open, switch the positions
00621     if (spawnflags & DOOR_START_OPEN)
00622     {
00623         VectorCopy(pos2, angles);
00624         VectorCopy(pos1, pos2);
00625         VectorCopy(angles, pos1);
00626         VectorInverse(movedir);
00627     } //end if
00628     //
00629     for (i = 0; i < brush->numsides; i++)
00630     {
00631         s = &brush->original_sides[i];
00632         s->planenum = AAS_TransformPlane(s->planenum, mapent->origin, pos2);
00633     } //end for
00634     //
00635     FreeBrushWindings(brush);
00636     AAS_MakeBrushWindings(brush);
00637     AddBrushBevels(brush);
00638     FreeBrushWindings(brush);
00639 } //end of the function AAS_PositionFuncRotatingBrush
00640 //===========================================================================
00641 //
00642 // Parameter:               -
00643 // Returns:                 -
00644 // Changes Globals:     -
00645 //===========================================================================
00646 void AAS_PositionBrush(entity_t *mapent, mapbrush_t *brush)
00647 {
00648     side_t *s;
00649     float newdist;
00650     int i, notteam;
00651     char *model;
00652 
00653     if (!strcmp(ValueForKey(mapent, "classname"), "func_door_rotating"))
00654     {
00655         AAS_PositionFuncRotatingBrush(mapent, brush);
00656     } //end if
00657     else
00658     {
00659         if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
00660         {
00661             for (i = 0; i < brush->numsides; i++)
00662             {
00663                 s = &brush->original_sides[i];
00664                 newdist = mapplanes[s->planenum].dist +
00665                         DotProduct(mapplanes[s->planenum].normal, mapent->origin);
00666                 s->planenum = FindFloatPlane(mapplanes[s->planenum].normal, newdist);
00667             } //end for
00668         } //end if
00669         //if it's a trigger hurt
00670         if (!strcmp("trigger_hurt", ValueForKey(mapent, "classname")))
00671         {
00672             notteam = FloatForKey(mapent, "bot_notteam");
00673             if ( notteam == 1 ) {
00674                 brush->contents |= CONTENTS_NOTTEAM1;
00675             }
00676             else if ( notteam == 2 ) {
00677                 brush->contents |= CONTENTS_NOTTEAM2;
00678             }
00679             else {
00680                 // always avoid so set lava contents
00681                 brush->contents |= CONTENTS_LAVA;
00682             }
00683         } //end if
00684         //
00685         else if (!strcmp("trigger_push", ValueForKey(mapent, "classname")))
00686         {
00687             //set the jumppad contents
00688             brush->contents = CONTENTS_JUMPPAD;
00689             //Log_Print("found trigger_push brush\n");
00690         } //end if
00691         //
00692         else if (!strcmp("trigger_multiple", ValueForKey(mapent, "classname")))
00693         {
00694             //set teleporter contents
00695             brush->contents = CONTENTS_TELEPORTER;
00696             //Log_Print("found trigger_multiple teleporter brush\n");
00697         } //end if
00698         //
00699         else if (!strcmp("trigger_teleport", ValueForKey(mapent, "classname")))
00700         {
00701             //set teleporter contents
00702             brush->contents = CONTENTS_TELEPORTER;
00703             //Log_Print("found trigger_teleport teleporter brush\n");
00704         } //end if
00705         else if (!strcmp("func_door", ValueForKey(mapent, "classname")))
00706         {
00707             //set mover contents
00708             brush->contents = CONTENTS_MOVER;
00709             //get the model number
00710             model = ValueForKey(mapent, "model");
00711             brush->modelnum = atoi(model+1);
00712         } //end if
00713     } //end else
00714 } //end of the function AAS_PositionBrush
00715 //===========================================================================
00716 // uses the global cfg_t cfg
00717 //
00718 // Parameter:               -
00719 // Returns:                 -
00720 // Changes Globals:     -
00721 //===========================================================================
00722 void AAS_CreateMapBrushes(mapbrush_t *brush, entity_t *mapent, int addbevels)
00723 {
00724     int i;
00725     //side_t *s;
00726     mapbrush_t *bboxbrushes[16];
00727 
00728     //if the brushes are not from an entity used for AAS
00729     if (!AAS_ValidEntity(mapent))
00730     {
00731         nummapbrushsides -= brush->numsides;
00732         brush->numsides = 0;
00733         return;
00734     } //end if
00735     //
00736     AAS_PositionBrush(mapent, brush);
00737     //from all normal solid brushes only the textured brush sides will
00738     //be used as bsp splitters, so set the right texinfo reference here
00739     AAS_SetTexinfo(brush);
00740     //remove contents detail flag, otherwise player clip contents won't be
00741     //bsped correctly for AAS!
00742     brush->contents &= ~CONTENTS_DETAIL;
00743     //if the brush has contents area portal it should be the only contents
00744     if (brush->contents & (CONTENTS_AREAPORTAL|CONTENTS_CLUSTERPORTAL))
00745     {
00746         brush->contents = CONTENTS_CLUSTERPORTAL;
00747         brush->leafnum = -1;
00748     } //end if
00749     //window and playerclip are used for player clipping, make them solid
00750     if (brush->contents & (CONTENTS_WINDOW | CONTENTS_PLAYERCLIP))
00751     {
00752         //
00753         brush->contents &= ~(CONTENTS_WINDOW | CONTENTS_PLAYERCLIP);
00754         brush->contents |= CONTENTS_SOLID;
00755         brush->leafnum = -1;
00756     } //end if
00757     //
00758     if (brush->contents & CONTENTS_BOTCLIP)
00759     {
00760         brush->contents = CONTENTS_SOLID;
00761         brush->leafnum = -1;
00762     } //end if
00763     //
00764     //Log_Write("brush %d contents = ", brush->brushnum);
00765     //PrintContents(brush->contents);
00766     //Log_Write("\r\n");
00767     //if not one of the following brushes then the brush is NOT used for AAS
00768     if (!(brush->contents & (CONTENTS_SOLID
00769                                     | CONTENTS_LADDER
00770                                     | CONTENTS_CLUSTERPORTAL
00771                                     | CONTENTS_DONOTENTER
00772                                     | CONTENTS_TELEPORTER
00773                                     | CONTENTS_JUMPPAD
00774                                     | CONTENTS_WATER
00775                                     | CONTENTS_LAVA
00776                                     | CONTENTS_SLIME
00777                                     | CONTENTS_MOVER
00778                                     )))
00779     {
00780         nummapbrushsides -= brush->numsides;
00781         brush->numsides = 0;
00782         return;
00783     } //end if
00784     //fix the map brush
00785     //AAS_FixMapBrush(brush);
00786     //if brush bevels should be added (for real map brushes, not bsp map brushes)
00787     if (addbevels)
00788     {
00789         //NOTE: we first have to get the mins and maxs of the brush before
00790         //          creating the brush bevels... the mins and maxs are used to
00791         //          create them. so we call MakeBrushWindings to get the mins
00792         //          and maxs and then after creating the bevels we free the
00793         //          windings because they are created for all sides (including
00794         //          bevels) a little later
00795         AAS_MakeBrushWindings(brush);
00796         AddBrushBevels(brush);
00797         FreeBrushWindings(brush);
00798     } //end if
00799     //NOTE: add the brush to the WORLD entity!!!
00800     mapent = &entities[0];
00801     //there's at least one new brush for now
00802     nummapbrushes++;
00803     mapent->numbrushes++;
00804     //liquid brushes are expanded for the maximum possible bounding box
00805     if (brush->contents & (CONTENTS_WATER
00806                                     | CONTENTS_LAVA
00807                                     | CONTENTS_SLIME 
00808                                     | CONTENTS_TELEPORTER
00809                                     | CONTENTS_JUMPPAD
00810                                     | CONTENTS_DONOTENTER
00811                                     | CONTENTS_MOVER
00812                                     ))
00813     {
00814         brush->expansionbbox = 0;
00815         //NOTE: the first bounding box is the max
00816         //FIXME: use max bounding box created from all bboxes
00817         AAS_ExpandMapBrush(brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs);
00818         AAS_MakeBrushWindings(brush);
00819     } //end if
00820     //area portal brushes are NOT expanded
00821     else if (brush->contents & CONTENTS_CLUSTERPORTAL)
00822     {
00823         brush->expansionbbox = 0;
00824         //NOTE: the first bounding box is the max
00825         //FIXME: use max bounding box created from all bboxes
00826         AAS_ExpandMapBrush(brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs);
00827         AAS_MakeBrushWindings(brush);
00828     } //end if
00829     //all solid brushes are expanded for all bounding boxes
00830     else if (brush->contents & (CONTENTS_SOLID
00831                                         | CONTENTS_LADDER
00832                                         ))
00833     {
00834         //brush for the first bounding box
00835         bboxbrushes[0] = brush;
00836         //make a copy for the other bounding boxes
00837         for (i = 1; i < cfg.numbboxes; i++)
00838         {
00839             bboxbrushes[i] = AAS_CopyMapBrush(brush, mapent);
00840         } //end for
00841         //expand every brush for it's bounding box and create windings
00842         for (i = 0; i < cfg.numbboxes; i++)
00843         {
00844             AAS_ExpandMapBrush(bboxbrushes[i], cfg.bboxes[i].mins, cfg.bboxes[i].maxs);
00845             bboxbrushes[i]->expansionbbox = cfg.bboxes[i].presencetype;
00846             AAS_MakeBrushWindings(bboxbrushes[i]);
00847         } //end for
00848     } //end else
00849 } //end of the function AAS_CreateMapBrushes

Generated on Thu Aug 25 12:37:14 2005 for Quake III Arena by  doxygen 1.3.9.1