📄 p_maputl.c
字号:
//**************************************************************************//**//** p_maputl.c : Heretic 2 : Raven Software, Corp.//**//** $RCSfile: p_maputl.c,v $//** $Revision: 1.11 $//** $Date: 95/10/04 02:39:28 $//** $Author: paul $//**//**************************************************************************#include "h2def.h"#include "p_local.h"static mobj_t *RoughBlockCheck(mobj_t *mo, int index);/*===================== P_AproxDistance== Gives an estimation of distance (not exact)====================*/fixed_t P_AproxDistance (fixed_t dx, fixed_t dy){ dx = abs(dx); dy = abs(dy); if (dx < dy) return dx+dy-(dx>>1); return dx+dy-(dy>>1);}/*==================== P_PointOnLineSide== Returns 0 or 1==================*/int P_PointOnLineSide (fixed_t x, fixed_t y, line_t *line){ fixed_t dx,dy; fixed_t left, right; if (!line->dx) { if (x <= line->v1->x) return line->dy > 0; return line->dy < 0; } if (!line->dy) { if (y <= line->v1->y) return line->dx < 0; return line->dx > 0; } dx = (x - line->v1->x); dy = (y - line->v1->y); left = FixedMul ( line->dy>>FRACBITS , dx ); right = FixedMul ( dy , line->dx>>FRACBITS ); if (right < left) return 0; // front side return 1; // back side}/*=================== P_BoxOnLineSide== Considers the line to be infinite= Returns side 0 or 1, -1 if box crosses the line=================*/int P_BoxOnLineSide (fixed_t *tmbox, line_t *ld){ int p1, p2; switch (ld->slopetype) { case ST_HORIZONTAL: p1 = tmbox[BOXTOP] > ld->v1->y; p2 = tmbox[BOXBOTTOM] > ld->v1->y; if (ld->dx < 0) { p1 ^= 1; p2 ^= 1; } break; case ST_VERTICAL: p1 = tmbox[BOXRIGHT] < ld->v1->x; p2 = tmbox[BOXLEFT] < ld->v1->x; if (ld->dy < 0) { p1 ^= 1; p2 ^= 1; } break; case ST_POSITIVE: p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld); p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld); break; case ST_NEGATIVE: p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld); p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld); break; } if (p1 == p2) return p1; return -1;}/*==================== P_PointOnDivlineSide== Returns 0 or 1==================*/int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t *line){ fixed_t dx,dy; fixed_t left, right; if (!line->dx) { if (x <= line->x) return line->dy > 0; return line->dy < 0; } if (!line->dy) { if (y <= line->y) return line->dx < 0; return line->dx > 0; } dx = (x - line->x); dy = (y - line->y);// try to quickly decide by looking at sign bits if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 ) { if ( (line->dy ^ dx) & 0x80000000 ) return 1; // (left is negative) return 0; } left = FixedMul ( line->dy>>8, dx>>8 ); right = FixedMul ( dy>>8 , line->dx>>8 ); if (right < left) return 0; // front side return 1; // back side}/*================ P_MakeDivline===============*/void P_MakeDivline (line_t *li, divline_t *dl){ dl->x = li->v1->x; dl->y = li->v1->y; dl->dx = li->dx; dl->dy = li->dy;}/*================= P_InterceptVector== Returns the fractional intercept point along the first divline== This is only called by the addthings and addlines traversers===============*/fixed_t P_InterceptVector (divline_t *v2, divline_t *v1){#if 1 fixed_t frac, num, den; den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy); if (den == 0) return 0;// I_Error ("P_InterceptVector: parallel"); num = FixedMul ( (v1->x - v2->x)>>8 ,v1->dy) + FixedMul ( (v2->y - v1->y)>>8 , v1->dx); frac = FixedDiv (num , den); return frac;#elsefloat frac, num, den, v1x,v1y,v1dx,v1dy,v2x,v2y,v2dx,v2dy; v1x = (float)v1->x/FRACUNIT; v1y = (float)v1->y/FRACUNIT; v1dx = (float)v1->dx/FRACUNIT; v1dy = (float)v1->dy/FRACUNIT; v2x = (float)v2->x/FRACUNIT; v2y = (float)v2->y/FRACUNIT; v2dx = (float)v2->dx/FRACUNIT; v2dy = (float)v2->dy/FRACUNIT; den = v1dy*v2dx - v1dx*v2dy; if (den == 0) return 0; // parallel num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx; frac = num / den; return frac*FRACUNIT;#endif}/*==================== P_LineOpening== Sets opentop and openbottom to the window through a two sided line= OPTIMIZE: keep this precalculated==================*/fixed_t opentop, openbottom, openrange;fixed_t lowfloor;void P_LineOpening (line_t *linedef){ sector_t *front, *back; if (linedef->sidenum[1] == -1) { // single sided line openrange = 0; return; } front = linedef->frontsector; back = linedef->backsector; if (front->ceilingheight < back->ceilingheight) opentop = front->ceilingheight; else opentop = back->ceilingheight; if (front->floorheight > back->floorheight) { openbottom = front->floorheight; lowfloor = back->floorheight; tmfloorpic = front->floorpic; } else { openbottom = back->floorheight; lowfloor = front->floorheight; tmfloorpic = back->floorpic; } openrange = opentop - openbottom;}/*=============================================================================== THING POSITION SETTING===============================================================================*//*===================== P_UnsetThingPosition== Unlinks a thing from block map and sectors====================*/void P_UnsetThingPosition (mobj_t *thing){ int blockx, blocky; if ( ! (thing->flags & MF_NOSECTOR) ) { // inert things don't need to be in blockmap// unlink from subsector if (thing->snext) thing->snext->sprev = thing->sprev; if (thing->sprev) thing->sprev->snext = thing->snext; else thing->subsector->sector->thinglist = thing->snext; } if ( ! (thing->flags & MF_NOBLOCKMAP) ) { // inert things don't need to be in blockmap// unlink from block map if (thing->bnext) thing->bnext->bprev = thing->bprev; if (thing->bprev) thing->bprev->bnext = thing->bnext; else { blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; if (blockx>=0 && blockx < bmapwidth && blocky>=0 && blocky <bmapheight) blocklinks[blocky*bmapwidth+blockx] = thing->bnext; } }}/*===================== P_SetThingPosition== Links a thing into both a block and a subsector based on it's x y= Sets thing->subsector properly====================*/void P_SetThingPosition (mobj_t *thing){ subsector_t *ss; sector_t *sec; int blockx, blocky; mobj_t **link;//// link into subsector// ss = R_PointInSubsector (thing->x,thing->y); thing->subsector = ss; if ( ! (thing->flags & MF_NOSECTOR) ) { // invisible things don't go into the sector links sec = ss->sector; thing->sprev = NULL; thing->snext = sec->thinglist; if (sec->thinglist) sec->thinglist->sprev = thing; sec->thinglist = thing; }//// link into blockmap// if ( ! (thing->flags & MF_NOBLOCKMAP) ) { // inert things don't need to be in blockmap blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; if (blockx>=0 && blockx < bmapwidth && blocky>=0 && blocky <bmapheight) { link = &blocklinks[blocky*bmapwidth+blockx]; thing->bprev = NULL; thing->bnext = *link; if (*link) (*link)->bprev = thing; *link = thing; } else { // thing is off the map thing->bnext = thing->bprev = NULL; } }}/*=============================================================================== BLOCK MAP ITERATORSFor each line/thing in the given mapblock, call the passed function.If the function returns false, exit with false without checking anything else.===============================================================================*//*==================== P_BlockLinesIterator== The validcount flags are used to avoid checking lines= that are marked in multiple mapblocks, so increment validcount before= the first call to P_BlockLinesIterator, then make one or more calls to it===================*/boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ){ int offset; short *list; line_t *ld; int i; polyblock_t *polyLink; seg_t **tempSeg; extern polyblock_t **PolyBlockMap; if (x < 0 || y<0 || x>=bmapwidth || y>=bmapheight) return true; offset = y*bmapwidth+x; polyLink = PolyBlockMap[offset]; while(polyLink) { if(polyLink->polyobj) { if(polyLink->polyobj->validcount != validcount) { polyLink->polyobj->validcount = validcount; tempSeg = polyLink->polyobj->segs; for(i = 0; i < polyLink->polyobj->numsegs; i++, tempSeg++) { if((*tempSeg)->linedef->validcount == validcount) { continue; } (*tempSeg)->linedef->validcount = validcount; if(!func((*tempSeg)->linedef)) { return false; } } } } polyLink = polyLink->next; } offset = *(blockmap+offset); for ( list = blockmaplump+offset ; *list != -1 ; list++) { ld = &lines[*list]; if (ld->validcount == validcount) continue; // line has already been checked ld->validcount = validcount; if ( !func(ld) ) return false; } return true; // everything was checked}/*==================== P_BlockThingsIterator===================*/boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ){ mobj_t *mobj; if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) return true; for (mobj = blocklinks[y*bmapwidth+x] ; mobj ; mobj = mobj->bnext) if (!func( mobj ) ) return false; return true;}/*=============================================================================== INTERCEPT ROUTINES===============================================================================*/intercept_t intercepts[MAXINTERCEPTS], *intercept_p;divline_t trace;boolean earlyout;int ptflags;/*==================== PIT_AddLineIntercepts== Looks for lines in the given block that intercept the given trace= to add to the intercepts list= A line is crossed if its endpoints are on opposite sides of the trace= Returns true if earlyout and a solid line hit==================*/boolean PIT_AddLineIntercepts (line_t *ld){ int s1, s2; fixed_t frac; divline_t dl;// avoid precision problems with two routines
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -