mirror of
https://github.com/id-Software/DOOM.git
synced 2026-03-20 00:49:46 +01:00
The DOOM sources as originally released on December 23, 1997
This commit is contained in:
349
linuxdoom-1.10/p_sight.c
Normal file
349
linuxdoom-1.10/p_sight.c
Normal file
@@ -0,0 +1,349 @@
|
||||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id:$
|
||||
//
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
//
|
||||
// This source is available for distribution and/or modification
|
||||
// only under the terms of the DOOM Source Code License as
|
||||
// published by id Software. All rights reserved.
|
||||
//
|
||||
// The source is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||
// for more details.
|
||||
//
|
||||
// $Log:$
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// LineOfSight/Visibility checks, uses REJECT Lookup Table.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static const char
|
||||
rcsid[] = "$Id: p_sight.c,v 1.3 1997/01/28 22:08:28 b1 Exp $";
|
||||
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
#include "i_system.h"
|
||||
#include "p_local.h"
|
||||
|
||||
// State.
|
||||
#include "r_state.h"
|
||||
|
||||
//
|
||||
// P_CheckSight
|
||||
//
|
||||
fixed_t sightzstart; // eye z of looker
|
||||
fixed_t topslope;
|
||||
fixed_t bottomslope; // slopes to top and bottom of target
|
||||
|
||||
divline_t strace; // from t1 to t2
|
||||
fixed_t t2x;
|
||||
fixed_t t2y;
|
||||
|
||||
int sightcounts[2];
|
||||
|
||||
|
||||
//
|
||||
// P_DivlineSide
|
||||
// Returns side 0 (front), 1 (back), or 2 (on).
|
||||
//
|
||||
int
|
||||
P_DivlineSide
|
||||
( fixed_t x,
|
||||
fixed_t y,
|
||||
divline_t* node )
|
||||
{
|
||||
fixed_t dx;
|
||||
fixed_t dy;
|
||||
fixed_t left;
|
||||
fixed_t right;
|
||||
|
||||
if (!node->dx)
|
||||
{
|
||||
if (x==node->x)
|
||||
return 2;
|
||||
|
||||
if (x <= node->x)
|
||||
return node->dy > 0;
|
||||
|
||||
return node->dy < 0;
|
||||
}
|
||||
|
||||
if (!node->dy)
|
||||
{
|
||||
if (x==node->y)
|
||||
return 2;
|
||||
|
||||
if (y <= node->y)
|
||||
return node->dx < 0;
|
||||
|
||||
return node->dx > 0;
|
||||
}
|
||||
|
||||
dx = (x - node->x);
|
||||
dy = (y - node->y);
|
||||
|
||||
left = (node->dy>>FRACBITS) * (dx>>FRACBITS);
|
||||
right = (dy>>FRACBITS) * (node->dx>>FRACBITS);
|
||||
|
||||
if (right < left)
|
||||
return 0; // front side
|
||||
|
||||
if (left == right)
|
||||
return 2;
|
||||
return 1; // back side
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_InterceptVector2
|
||||
// Returns the fractional intercept point
|
||||
// along the first divline.
|
||||
// This is only called by the addthings and addlines traversers.
|
||||
//
|
||||
fixed_t
|
||||
P_InterceptVector2
|
||||
( divline_t* v2,
|
||||
divline_t* v1 )
|
||||
{
|
||||
fixed_t frac;
|
||||
fixed_t num;
|
||||
fixed_t 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;
|
||||
}
|
||||
|
||||
//
|
||||
// P_CrossSubsector
|
||||
// Returns true
|
||||
// if strace crosses the given subsector successfully.
|
||||
//
|
||||
boolean P_CrossSubsector (int num)
|
||||
{
|
||||
seg_t* seg;
|
||||
line_t* line;
|
||||
int s1;
|
||||
int s2;
|
||||
int count;
|
||||
subsector_t* sub;
|
||||
sector_t* front;
|
||||
sector_t* back;
|
||||
fixed_t opentop;
|
||||
fixed_t openbottom;
|
||||
divline_t divl;
|
||||
vertex_t* v1;
|
||||
vertex_t* v2;
|
||||
fixed_t frac;
|
||||
fixed_t slope;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (num>=numsubsectors)
|
||||
I_Error ("P_CrossSubsector: ss %i with numss = %i",
|
||||
num,
|
||||
numsubsectors);
|
||||
#endif
|
||||
|
||||
sub = &subsectors[num];
|
||||
|
||||
// check lines
|
||||
count = sub->numlines;
|
||||
seg = &segs[sub->firstline];
|
||||
|
||||
for ( ; count ; seg++, count--)
|
||||
{
|
||||
line = seg->linedef;
|
||||
|
||||
// allready checked other side?
|
||||
if (line->validcount == validcount)
|
||||
continue;
|
||||
|
||||
line->validcount = validcount;
|
||||
|
||||
v1 = line->v1;
|
||||
v2 = line->v2;
|
||||
s1 = P_DivlineSide (v1->x,v1->y, &strace);
|
||||
s2 = P_DivlineSide (v2->x, v2->y, &strace);
|
||||
|
||||
// line isn't crossed?
|
||||
if (s1 == s2)
|
||||
continue;
|
||||
|
||||
divl.x = v1->x;
|
||||
divl.y = v1->y;
|
||||
divl.dx = v2->x - v1->x;
|
||||
divl.dy = v2->y - v1->y;
|
||||
s1 = P_DivlineSide (strace.x, strace.y, &divl);
|
||||
s2 = P_DivlineSide (t2x, t2y, &divl);
|
||||
|
||||
// line isn't crossed?
|
||||
if (s1 == s2)
|
||||
continue;
|
||||
|
||||
// stop because it is not two sided anyway
|
||||
// might do this after updating validcount?
|
||||
if ( !(line->flags & ML_TWOSIDED) )
|
||||
return false;
|
||||
|
||||
// crosses a two sided line
|
||||
front = seg->frontsector;
|
||||
back = seg->backsector;
|
||||
|
||||
// no wall to block sight with?
|
||||
if (front->floorheight == back->floorheight
|
||||
&& front->ceilingheight == back->ceilingheight)
|
||||
continue;
|
||||
|
||||
// possible occluder
|
||||
// because of ceiling height differences
|
||||
if (front->ceilingheight < back->ceilingheight)
|
||||
opentop = front->ceilingheight;
|
||||
else
|
||||
opentop = back->ceilingheight;
|
||||
|
||||
// because of ceiling height differences
|
||||
if (front->floorheight > back->floorheight)
|
||||
openbottom = front->floorheight;
|
||||
else
|
||||
openbottom = back->floorheight;
|
||||
|
||||
// quick test for totally closed doors
|
||||
if (openbottom >= opentop)
|
||||
return false; // stop
|
||||
|
||||
frac = P_InterceptVector2 (&strace, &divl);
|
||||
|
||||
if (front->floorheight != back->floorheight)
|
||||
{
|
||||
slope = FixedDiv (openbottom - sightzstart , frac);
|
||||
if (slope > bottomslope)
|
||||
bottomslope = slope;
|
||||
}
|
||||
|
||||
if (front->ceilingheight != back->ceilingheight)
|
||||
{
|
||||
slope = FixedDiv (opentop - sightzstart , frac);
|
||||
if (slope < topslope)
|
||||
topslope = slope;
|
||||
}
|
||||
|
||||
if (topslope <= bottomslope)
|
||||
return false; // stop
|
||||
}
|
||||
// passed the subsector ok
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_CrossBSPNode
|
||||
// Returns true
|
||||
// if strace crosses the given node successfully.
|
||||
//
|
||||
boolean P_CrossBSPNode (int bspnum)
|
||||
{
|
||||
node_t* bsp;
|
||||
int side;
|
||||
|
||||
if (bspnum & NF_SUBSECTOR)
|
||||
{
|
||||
if (bspnum == -1)
|
||||
return P_CrossSubsector (0);
|
||||
else
|
||||
return P_CrossSubsector (bspnum&(~NF_SUBSECTOR));
|
||||
}
|
||||
|
||||
bsp = &nodes[bspnum];
|
||||
|
||||
// decide which side the start point is on
|
||||
side = P_DivlineSide (strace.x, strace.y, (divline_t *)bsp);
|
||||
if (side == 2)
|
||||
side = 0; // an "on" should cross both sides
|
||||
|
||||
// cross the starting side
|
||||
if (!P_CrossBSPNode (bsp->children[side]) )
|
||||
return false;
|
||||
|
||||
// the partition plane is crossed here
|
||||
if (side == P_DivlineSide (t2x, t2y,(divline_t *)bsp))
|
||||
{
|
||||
// the line doesn't touch the other side
|
||||
return true;
|
||||
}
|
||||
|
||||
// cross the ending side
|
||||
return P_CrossBSPNode (bsp->children[side^1]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_CheckSight
|
||||
// Returns true
|
||||
// if a straight line between t1 and t2 is unobstructed.
|
||||
// Uses REJECT.
|
||||
//
|
||||
boolean
|
||||
P_CheckSight
|
||||
( mobj_t* t1,
|
||||
mobj_t* t2 )
|
||||
{
|
||||
int s1;
|
||||
int s2;
|
||||
int pnum;
|
||||
int bytenum;
|
||||
int bitnum;
|
||||
|
||||
// First check for trivial rejection.
|
||||
|
||||
// Determine subsector entries in REJECT table.
|
||||
s1 = (t1->subsector->sector - sectors);
|
||||
s2 = (t2->subsector->sector - sectors);
|
||||
pnum = s1*numsectors + s2;
|
||||
bytenum = pnum>>3;
|
||||
bitnum = 1 << (pnum&7);
|
||||
|
||||
// Check in REJECT table.
|
||||
if (rejectmatrix[bytenum]&bitnum)
|
||||
{
|
||||
sightcounts[0]++;
|
||||
|
||||
// can't possibly be connected
|
||||
return false;
|
||||
}
|
||||
|
||||
// An unobstructed LOS is possible.
|
||||
// Now look from eyes of t1 to any part of t2.
|
||||
sightcounts[1]++;
|
||||
|
||||
validcount++;
|
||||
|
||||
sightzstart = t1->z + t1->height - (t1->height>>2);
|
||||
topslope = (t2->z+t2->height) - sightzstart;
|
||||
bottomslope = (t2->z) - sightzstart;
|
||||
|
||||
strace.x = t1->x;
|
||||
strace.y = t1->y;
|
||||
t2x = t2->x;
|
||||
t2y = t2->y;
|
||||
strace.dx = t2->x - t1->x;
|
||||
strace.dy = t2->y - t1->y;
|
||||
|
||||
// the head node is the last node output
|
||||
return P_CrossBSPNode (numnodes-1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user