Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Jisk/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
117 results
Select Git revision
Show changes
Commits on Source (4)
...@@ -69,6 +69,7 @@ r_patch.c ...@@ -69,6 +69,7 @@ r_patch.c
r_patchrotation.c r_patchrotation.c
r_picformats.c r_picformats.c
r_portal.c r_portal.c
nodebuilder.c
screen.c screen.c
taglist.c taglist.c
v_video.c v_video.c
......
...@@ -49,6 +49,20 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f) ...@@ -49,6 +49,20 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f)
return (fixed_t)(f * FRACUNIT); return (fixed_t)(f * FRACUNIT);
} }
/*!
\brief convert fixed_t into a double
*/
FUNCMATH FUNCINLINE static ATTRINLINE double FixedToDouble(fixed_t x)
{
return x / (double)FRACUNIT;
}
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t DoubleToFixed(double f)
{
return (fixed_t)(f * FRACUNIT);
}
// for backwards compat // for backwards compat
#define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT)) #define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT))
#define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT)) #define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT))
......
This diff is collapsed.
#ifndef __NODEBUILDER_H__
#define __NODEBUILDER_H__
#include "doomdef.h"
#include "doomdata.h"
#include "doomtype.h"
#include "r_defs.h"
typedef struct FPrivSeg_s
{
INT32 v1, v2;
fixed_t linev1x, linev1y;
fixed_t linev2x, linev2y;
INT32 sidedef;
INT32 linedef;
INT32 side;
fixed_t length;
fixed_t offset;
angle_t angle;
sector_t *frontsector;
sector_t *backsector;
polynode_t *polynode;
sector_t *polysector;
boolean backside;
UINT32 next;
INT32 planenum;
boolean planefront;
} FPrivSeg;
typedef struct FPrivVert_s
{
fixed_t x, y;
} FPrivVert;
typedef struct FSimpleLine_s
{
fixed_t x, y, dx, dy;
} FSimpleLine;
typedef union USegPtr_s
{
UINT32 SegNum;
FPrivSeg *SegPtr;
} USegPtr;
typedef struct
{
node_t *Nodes;
subsector_t *Subsectors;
UINT32 *SubsectorSets;
FPrivSeg *Segs;
FPrivVert *Vertices;
USegPtr *SegList;
UINT8 *PlaneChecked;
FSimpleLine *Planes;
INT32 NumNodes;
INT32 NumSubsectors;
INT32 NumSubsectorSets;
INT32 NumSegs;
INT32 NumVertices;
INT32 SegListSize;
INT32 NumPlaneChecked;
INT32 NumPlanes;
} NodeBuilder;
void NodeBuilder_Set(NodeBuilder *nb);
void NodeBuilder_Clear(void);
void NodeBuilder_AddSegs(seg_t *seglist, size_t segcount);
void NodeBuilder_AddPolySegs(polynode_t *node);
void NodeBuilder_BuildMini(void);
void NodeBuilder_ExtractMini(minibsp_t *bsp);
#endif // __NODEBUILDER_H__
...@@ -11,8 +11,6 @@ ...@@ -11,8 +11,6 @@
/// \brief Movable segs like in Hexen, but more flexible /// \brief Movable segs like in Hexen, but more flexible
/// due to application of dynamic binary space partitioning theory. /// due to application of dynamic binary space partitioning theory.
// haleyjd: temporary define
#include "z_zone.h" #include "z_zone.h"
#include "doomstat.h" #include "doomstat.h"
...@@ -359,7 +357,7 @@ static void Polyobj_findSegs(polyobj_t *po, seg_t *seg) ...@@ -359,7 +357,7 @@ static void Polyobj_findSegs(polyobj_t *po, seg_t *seg)
if (!(po->flags & POF_ONESIDE)) if (!(po->flags & POF_ONESIDE))
{ {
// Find backfacings // Find backfacings
for (s = 0; s < numsegs; s++) for (s = 0; s < numsegs; s++)
{ {
size_t r; size_t r;
...@@ -381,7 +379,7 @@ static void Polyobj_findSegs(polyobj_t *po, seg_t *seg) ...@@ -381,7 +379,7 @@ static void Polyobj_findSegs(polyobj_t *po, seg_t *seg)
if (r != po->segCount) if (r != po->segCount)
continue; continue;
segs[s].dontrenderme = true; segs[s].polybackside = true;
Polyobj_addSeg(po, &segs[s]); Polyobj_addSeg(po, &segs[s]);
} }
...@@ -451,7 +449,7 @@ newseg: ...@@ -451,7 +449,7 @@ newseg:
if (r != po->segCount) if (r != po->segCount)
continue; continue;
segs[q].dontrenderme = true; segs[q].polybackside = true;
Polyobj_addSeg(po, &segs[q]); Polyobj_addSeg(po, &segs[q]);
} }
} }
...@@ -644,6 +642,459 @@ static void Polyobj_removeFromSubsec(polyobj_t *po) ...@@ -644,6 +642,459 @@ static void Polyobj_removeFromSubsec(polyobj_t *po)
} }
} }
//==========================================================================
//
// TArray for segs
//
//==========================================================================
typedef struct segarray_s
{
size_t size;
size_t alloc;
polyseg_t *elements;
} segarray_t;
static void SegArray_Clear(segarray_t *array)
{
array->size = 0;
array->alloc = 0;
Z_Free(array->elements);
array->elements = NULL;
}
static void SegArray_Push(segarray_t *array, polyseg_t *element)
{
array->size++;
if (array->size >= array->alloc)
{
array->alloc = array->alloc ? array->alloc*2 : 8;
array->elements = Z_Realloc(array->elements, array->alloc * sizeof(polyseg_t), PU_STATIC, NULL);
}
memcpy(&array->elements[array->size - 1], element, sizeof(polyseg_t));
}
static polyseg_t *SegArray_Last(segarray_t *array)
{
return &(array->elements[array->size - 1]);
}
static void SegArray_Copy(segarray_t *list, polynode_t *node)
{
size_t i;
node->numsegs = list->size;
node->segs = Z_Malloc(node->numsegs * sizeof(polyseg_t), PU_LEVEL, NULL);
for (i = 0; i < list->size; i++)
{
polyseg_t *src = &list->elements[i];
polyseg_t *pseg = &node->segs[i];
pseg->v1.x = src->v1.x;
pseg->v1.y = src->v1.y;
pseg->v2.x = src->v2.x;
pseg->v2.y = src->v2.y;
pseg->wall = src->wall;
}
}
//==========================================================================
//
// NewPolyNode
//
//==========================================================================
static polynode_t *FreePolyNodes;
static polynode_t *NewPolyNode(void)
{
polynode_t *node;
if (FreePolyNodes != NULL)
{
node = FreePolyNodes;
FreePolyNodes = node->pnext;
}
else
node = Z_Malloc(sizeof(polynode_t), PU_LEVEL, NULL);
node->poly = NULL;
node->pnext = NULL;
node->pprev = NULL;
node->subsector = NULL;
node->snext = NULL;
return node;
}
//==========================================================================
//
// FreePolyNode
//
//==========================================================================
static void FreePolyNode(polynode_t *node)
{
Z_Free(node->segs);
node->segs = NULL;
node->numsegs = 0;
node->pnext = FreePolyNodes;
FreePolyNodes = node;
}
//==========================================================================
//
// ReleaseAllPolyNodes
//
//==========================================================================
static void ReleaseAllPolyNodes(void)
{
polynode_t *node, *next;
for (node = FreePolyNodes; node != NULL; node = next)
{
next = node->pnext;
Z_Free(node);
}
FreePolyNodes = NULL;
}
//==========================================================================
//
// ClearSubsectorLinks
//
//==========================================================================
void Polyobj_ClearSubsectorLinks(polyobj_t *polyobj)
{
while (polyobj->subsectorlinks != NULL)
{
polynode_t *link = polyobj->subsectorlinks;
polynode_t *next = link->snext;
subsector_t *sub = link->subsector;
if (link->pnext != NULL)
link->pnext->pprev = link->pprev;
if (link->pprev != NULL)
link->pprev->pnext = link->pnext;
else
sub->polynodes = link->pnext;
if (sub->BSP != NULL)
sub->BSP->dirty = true;
FreePolyNode(link);
polyobj->subsectorlinks = next;
}
polyobj->subsectorlinks = NULL;
}
void Polyobj_ClearAllSubsectorLinks(void)
{
INT32 i;
for (i = 0; i < numPolyObjects; i++)
{
if (PolyObjects[i].subsectorlinks == NULL)
Polyobj_ClearSubsectorLinks(&PolyObjects[i]);
}
ReleaseAllPolyNodes();
}
//==========================================================================
//
// GetIntersection
//
// adapted from P_InterceptVector
//
//==========================================================================
static boolean GetIntersection(polyseg_t *seg, node_t *bsp, polyobjvertex_t *v)
{
double frac;
double num;
double den;
double v2x = seg->v1.x;
double v2y = seg->v1.y;
double v2dx = seg->v2.x - v2x;
double v2dy = seg->v2.y - v2y;
double v1x = FixedToDouble(bsp->x);
double v1y = FixedToDouble(bsp->y);
double v1dx = FixedToDouble(bsp->dx);
double v1dy = FixedToDouble(bsp->dy);
den = v1dy*v2dx - v1dx*v2dy;
if (fpclassify(den) == FP_ZERO)
return false; // parallel
num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx;
frac = num / den;
if (frac < 0.0 || frac > 1.0)
return false;
v->x = v2x + frac * v2dx;
v->y = v2y + frac * v2dy;
return true;
}
//==========================================================================
//
// PartitionDistance
//
// Determine the distance of a vertex to a node's partition line.
//
//==========================================================================
static double PartitionDistance(polyobjvertex_t *vt, node_t *node)
{
double a = FixedToDouble(-node->dy) * (vt->x - FixedToDouble(node->x));
double b = FixedToDouble(node->dx) * (vt->y - FixedToDouble(node->y));
double len = FixedToDouble(node->length);
return fabs(a + b) / len;
}
//==========================================================================
//
// AddToBBox
//
//==========================================================================
static void AddToBBox(fixed_t child[4], fixed_t parent[4])
{
if (child[BOXTOP] > parent[BOXTOP])
parent[BOXTOP] = child[BOXTOP];
if (child[BOXBOTTOM] < parent[BOXBOTTOM])
parent[BOXBOTTOM] = child[BOXBOTTOM];
if (child[BOXLEFT] < parent[BOXLEFT])
parent[BOXLEFT] = child[BOXLEFT];
if (child[BOXRIGHT] > parent[BOXRIGHT])
parent[BOXRIGHT] = child[BOXRIGHT];
}
//==========================================================================
//
// AddPolyVertexToBBox
//
//==========================================================================
static void AddPolyVertexToBBox(polyobjvertex_t *v, fixed_t bbox[4])
{
fixed_t x = DoubleToFixed(v->x);
fixed_t y = DoubleToFixed(v->y);
if (x < bbox[BOXLEFT])
bbox[BOXLEFT] = x;
if (x > bbox[BOXRIGHT])
bbox[BOXRIGHT] = x;
if (y < bbox[BOXBOTTOM])
bbox[BOXBOTTOM] = y;
if (y > bbox[BOXTOP])
bbox[BOXTOP] = y;
}
//==========================================================================
//
// SplitPoly
//
//==========================================================================
static void SplitPoly(polynode_t *pnode, INT32 bspnum, fixed_t bbox[4])
{
static segarray_t lists[2];
static const double POLY_EPSILON = 0.3125;
size_t i;
if (!(bspnum & NF_SUBSECTOR)) // Keep going until found a subsector
{
node_t *bsp = &nodes[bspnum];
INT32 centerside = R_PointOnSide(pnode->poly->centerPt.x, pnode->poly->centerPt.y, bsp);
SegArray_Clear(&lists[0]);
SegArray_Clear(&lists[1]);
for (i = 0; i < pnode->numsegs; i++)
{
polyseg_t *seg = &pnode->segs[i];
// Parts of the following code were taken from Eternity and are
// being used with permission.
// get distance of vertices from partition line
// If the distance is too small, we may decide to
// change our idea of sidedness.
double dist_v1 = PartitionDistance(&seg->v1, bsp);
double dist_v2 = PartitionDistance(&seg->v2, bsp);
// If the distances are less than epsilon, consider the points as being
// on the same side as the polyobj origin. Why? People like to build
// polyobject doors flush with their door tracks. This breaks using the
// usual assumptions.
// Addition to Eternity code: We must also check any seg with only one
// vertex inside the epsilon threshold. If not, these lines will get split but
// adjoining ones with both vertices inside the threshold won't thus messing up
// the order in which they get drawn.
if(dist_v1 <= POLY_EPSILON)
{
if (dist_v2 <= POLY_EPSILON)
SegArray_Push(&lists[centerside], seg);
else
{
INT32 side = R_PointOnSide(DoubleToFixed(seg->v2.x), DoubleToFixed(seg->v2.y), bsp);
SegArray_Push(&lists[side], seg);
}
}
else if (dist_v2 <= POLY_EPSILON)
{
INT32 side = R_PointOnSide(DoubleToFixed(seg->v1.x), DoubleToFixed(seg->v1.y), bsp);
SegArray_Push(&lists[side], seg);
}
else
{
INT32 side1 = R_PointOnSide(DoubleToFixed(seg->v1.x), DoubleToFixed(seg->v1.y), bsp);
INT32 side2 = R_PointOnSide(DoubleToFixed(seg->v2.x), DoubleToFixed(seg->v2.y), bsp);
if (side1 != side2)
{
// if the partition line crosses this seg, we must split it.
polyobjvertex_t vert;
if (GetIntersection(seg, bsp, &vert))
{
SegArray_Push(&lists[0], seg);
SegArray_Push(&lists[1], seg);
SegArray_Last(&lists[side1])->v2.x = vert.x;
SegArray_Last(&lists[side1])->v2.y = vert.y;
SegArray_Last(&lists[side2])->v1.x = vert.x;
SegArray_Last(&lists[side2])->v1.y = vert.y;
}
else
{
// should never happen
SegArray_Push(&lists[side1], seg);
}
}
else
{
// both points on the same side.
SegArray_Push(&lists[side1], seg);
}
}
}
if (lists[1].size == 0)
{
SplitPoly(pnode, bsp->children[0], bsp->bbox[0]);
AddToBBox(bsp->bbox[0], bbox);
}
else if (lists[0].size == 0)
{
SplitPoly(pnode, bsp->children[1], bsp->bbox[1]);
AddToBBox(bsp->bbox[1], bbox);
}
else
{
// create the new node
polynode_t *newnode = NewPolyNode();
newnode->poly = pnode->poly;
SegArray_Copy(&lists[1], newnode);
// set segs for original node
SegArray_Copy(&lists[0], pnode);
// recurse back side
SplitPoly(newnode, bsp->children[1], bsp->bbox[1]);
// recurse front side
SplitPoly(pnode, bsp->children[0], bsp->bbox[0]);
AddToBBox(bsp->bbox[0], bbox);
AddToBBox(bsp->bbox[1], bbox);
}
}
else
{
// we reached a subsector so we can link the node with this subsector
subsector_t *sub = &subsectors[bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR];
fixed_t subbbox[4] = { INT32_MIN, INT32_MAX, INT32_MAX, INT32_MIN };
// Link node to subsector
pnode->pnext = sub->polynodes;
if (pnode->pnext != NULL)
pnode->pnext->pprev = pnode;
pnode->pprev = NULL;
sub->polynodes = pnode;
// link node to polyobject
pnode->snext = pnode->poly->subsectorlinks;
pnode->poly->subsectorlinks = pnode;
pnode->subsector = sub;
// calculate bounding box for this polynode
for (i = 0; i < pnode->numsegs; ++i)
{
AddPolyVertexToBBox(&pnode->segs[i].v1, subbbox);
AddPolyVertexToBBox(&pnode->segs[i].v2, subbbox);
}
// Potentially expand the parent node's bounding box to contain these bits of polyobject.
AddToBBox(subbbox, bbox);
}
}
static void Polyobj_CreateSubsectorLinks(polyobj_t *polyobj)
{
polynode_t *node = NewPolyNode();
size_t i;
// Even though we don't care about it, we need to initialize this
// bounding box to something so that Valgrind won't complain about it
// when SplitPoly modifies it.
fixed_t dummybbox[4] = { 0, 0, 0, 0 };
node->poly = polyobj;
node->numsegs = polyobj->segCount;
node->segs = Z_Malloc(node->numsegs * sizeof(polyseg_t), PU_LEVEL, NULL);
for (i = 0; i < node->numsegs; i++)
{
polyseg_t *seg = &node->segs[i];
seg_t *line = polyobj->segs[i];
seg->v1.x = FixedToDouble(line->v1->x);
seg->v1.y = FixedToDouble(line->v1->y);
seg->v2.x = FixedToDouble(line->v2->x);
seg->v2.y = FixedToDouble(line->v2->y);
seg->wall = line;
}
SplitPoly(node, (INT32)numnodes - 1, dummybbox);
ReleaseAllPolyNodes();
}
void Polyobj_LinkToSubsectors(void)
{
INT32 i;
for (i = 0; i < numPolyObjects; i++)
{
if (PolyObjects[i].subsectorlinks == NULL)
Polyobj_CreateSubsectorLinks(&PolyObjects[i]);
}
}
// Blockmap Functions // Blockmap Functions
// Retrieves a polymaplink object from the free list or creates a new one. // Retrieves a polymaplink object from the free list or creates a new one.
...@@ -708,7 +1159,7 @@ static void Polyobj_linkToBlockmap(polyobj_t *po) ...@@ -708,7 +1159,7 @@ static void Polyobj_linkToBlockmap(polyobj_t *po)
{ {
if (!(x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)) if (!(x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight))
{ {
polymaplink_t *l = Polyobj_getLink(); polymaplink_t *l = Polyobj_getLink();
l->po = po; l->po = po;
...@@ -1028,6 +1479,7 @@ boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs) ...@@ -1028,6 +1479,7 @@ boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs)
Polyobj_removeFromSubsec(po); // unlink it from its subsector Polyobj_removeFromSubsec(po); // unlink it from its subsector
Polyobj_linkToBlockmap(po); // relink to blockmap Polyobj_linkToBlockmap(po); // relink to blockmap
Polyobj_attachToSubsec(po); // relink to subsector Polyobj_attachToSubsec(po); // relink to subsector
Polyobj_ClearSubsectorLinks(po);// clear its subsector links
} }
return !(hitflags & 2); return !(hitflags & 2);
...@@ -1227,9 +1679,10 @@ boolean Polyobj_rotate(polyobj_t *po, angle_t delta, boolean turnplayers, boolea ...@@ -1227,9 +1679,10 @@ boolean Polyobj_rotate(polyobj_t *po, angle_t delta, boolean turnplayers, boolea
po->angle += delta; po->angle += delta;
Polyobj_removeFromBlockmap(po); // unlink it from the blockmap Polyobj_removeFromBlockmap(po); // unlink it from the blockmap
Polyobj_removeFromSubsec(po); // remove from subsector Polyobj_removeFromSubsec(po); // unlink it from its subsector
Polyobj_linkToBlockmap(po); // relink to blockmap Polyobj_linkToBlockmap(po); // relink to blockmap
Polyobj_attachToSubsec(po); // relink to subsector Polyobj_attachToSubsec(po); // relink to subsector
Polyobj_ClearSubsectorLinks(po);// clear its subsector links
} }
return !(hitflags & 2); return !(hitflags & 2);
...@@ -2483,6 +2936,7 @@ void T_PolyObjFlag(polymove_t *th) ...@@ -2483,6 +2936,7 @@ void T_PolyObjFlag(polymove_t *th)
Polyobj_removeFromSubsec(po); // unlink it from its subsector Polyobj_removeFromSubsec(po); // unlink it from its subsector
Polyobj_linkToBlockmap(po); // relink to blockmap Polyobj_linkToBlockmap(po); // relink to blockmap
Polyobj_attachToSubsec(po); // relink to subsector Polyobj_attachToSubsec(po); // relink to subsector
Polyobj_ClearSubsectorLinks(po);// clear its subsector links
} }
boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata) boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
......
...@@ -66,6 +66,8 @@ typedef enum ...@@ -66,6 +66,8 @@ typedef enum
// Polyobject Structure // Polyobject Structure
// //
struct polynode_s;
typedef struct polyobj_s typedef struct polyobj_s
{ {
mdllistitem_t link; // for subsector links; must be first mdllistitem_t link; // for subsector links; must be first
...@@ -76,8 +78,8 @@ typedef struct polyobj_s ...@@ -76,8 +78,8 @@ typedef struct polyobj_s
INT32 parent; // numeric id of parent polyobject INT32 parent; // numeric id of parent polyobject
size_t segCount; // number of segs in polyobject size_t segCount; // number of segs in polyobject
size_t numSegsAlloc; // number of segs allocated size_t numSegsAlloc; // number of segs allocated
struct seg_s **segs; // the segs, a reallocating array. struct seg_s **segs; // the segs, a reallocating array.
size_t numVertices; // number of vertices (generally == segCount) size_t numVertices; // number of vertices (generally == segCount)
...@@ -86,18 +88,19 @@ typedef struct polyobj_s ...@@ -86,18 +88,19 @@ typedef struct polyobj_s
vertex_t *tmpVerts; // temporary vertex backups for rotation vertex_t *tmpVerts; // temporary vertex backups for rotation
vertex_t **vertices; // vertices this polyobject must move vertex_t **vertices; // vertices this polyobject must move
size_t numLines; // number of linedefs (generally <= segCount) size_t numLines; // number of linedefs (generally <= segCount)
size_t numLinesAlloc; // number of linedefs allocated size_t numLinesAlloc; // number of linedefs allocated
struct line_s **lines; // linedefs this polyobject must move struct line_s **lines; // linedefs this polyobject must move
degenmobj_t spawnSpot; // location of spawn spot degenmobj_t spawnSpot; // location of spawn spot
vertex_t centerPt; // center point vertex_t centerPt; // center point
fixed_t zdist; // viewz distance for sorting fixed_t zdist; // viewz distance for sorting
angle_t angle; // for rotation angle_t angle; // for rotation
UINT8 attached; // if true, is attached to a subsector UINT8 attached; // if true, is attached to a subsector
struct polynode_s *subsectorlinks;
fixed_t blockbox[4]; // bounding box for clipping fixed_t blockbox[4]; // bounding box for clipping
UINT8 linked; // is linked to blockmap UINT8 linked; // is linked to blockmap
size_t validcount; // for clipping: prevents multiple checks size_t validcount; // for clipping: prevents multiple checks
INT32 damage; // damage to inflict on stuck things INT32 damage; // damage to inflict on stuck things
fixed_t thrust; // amount of thrust to put on blocking objects fixed_t thrust; // amount of thrust to put on blocking objects
...@@ -105,17 +108,41 @@ typedef struct polyobj_s ...@@ -105,17 +108,41 @@ typedef struct polyobj_s
thinker_t *thinker; // pointer to a thinker affecting this polyobj thinker_t *thinker; // pointer to a thinker affecting this polyobj
UINT8 isBad; // a bad polyobject: should not be rendered/manipulated UINT8 isBad; // a bad polyobject: should not be rendered/manipulated
INT32 translucency; // index to translucency tables INT32 translucency; // index to translucency tables
INT16 triggertag; // Tag of linedef executor to trigger on touch INT16 triggertag; // Tag of linedef executor to trigger on touch
struct visplane_s *visplane; // polyobject's visplane, for ease of putting into the list later
// these are saved for netgames, so do not let Lua touch these! // these are saved for netgames, so do not let Lua touch these!
INT32 spawnflags; // Flags the polyobject originally spawned with INT32 spawnflags; // Flags the polyobject originally spawned with
INT32 spawntrans; // Translucency the polyobject originally spawned with INT32 spawntrans; // Translucency the polyobject originally spawned with
} polyobj_t; } polyobj_t;
typedef struct polyobjvertex_s
{
double x, y;
} polyobjvertex_t;
typedef struct polyseg_s
{
polyobjvertex_t v1;
polyobjvertex_t v2;
struct seg_s *wall;
} polyseg_t;
typedef struct polynode_s
{
polyobj_t *poly; // owning polyobject
struct polynode_s *pnext; // next polyobj in list
struct polynode_s *pprev; // previous polyobj
struct subsector_s *subsector; // containing subsector
struct polynode_s *snext; // next subsector
polyseg_t *segs; // segs for this node
size_t numsegs;
} polynode_t;
// //
// Polyobject Blockmap Link Structure // Polyobject Blockmap Link Structure
// //
...@@ -372,10 +399,14 @@ typedef struct polyfadedata_s ...@@ -372,10 +399,14 @@ typedef struct polyfadedata_s
// Functions // Functions
// //
void Polyobj_InitLevel(void);
void Polyobj_LinkToSubsectors(void);
void Polyobj_ClearSubsectorLinks(polyobj_t *polyobj);
void Polyobj_ClearAllSubsectorLinks(void);
boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs); boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs);
boolean Polyobj_rotate(polyobj_t *po, angle_t delta, boolean turnplayers, boolean turnothers, boolean checkmobjs); boolean Polyobj_rotate(polyobj_t *po, angle_t delta, boolean turnplayers, boolean turnothers, boolean checkmobjs);
polyobj_t *Polyobj_GetForNum(INT32 id); polyobj_t *Polyobj_GetForNum(INT32 id);
void Polyobj_InitLevel(void);
void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y); void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y);
boolean P_PointInsidePolyobj(polyobj_t *po, fixed_t x, fixed_t y); boolean P_PointInsidePolyobj(polyobj_t *po, fixed_t x, fixed_t y);
boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo); boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo);
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include "m_argv.h" #include "m_argv.h"
#include "p_polyobj.h" #include "p_polyobj.h"
#include "nodebuilder.h"
#include "v_video.h" #include "v_video.h"
...@@ -3058,6 +3059,7 @@ static void P_LoadNodes(UINT8 *data) ...@@ -3058,6 +3059,7 @@ static void P_LoadNodes(UINT8 *data)
no->y = SHORT(mn->y)<<FRACBITS; no->y = SHORT(mn->y)<<FRACBITS;
no->dx = SHORT(mn->dx)<<FRACBITS; no->dx = SHORT(mn->dx)<<FRACBITS;
no->dy = SHORT(mn->dy)<<FRACBITS; no->dy = SHORT(mn->dy)<<FRACBITS;
no->length = FixedHypot(no->dx>>1, no->dy>>1)<<1;
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
{ {
no->children[j] = SHORT(mn->children[j]); no->children[j] = SHORT(mn->children[j]);
...@@ -3120,10 +3122,9 @@ static void P_InitializeSeg(seg_t *seg) ...@@ -3120,10 +3122,9 @@ static void P_InitializeSeg(seg_t *seg)
seg->lightmaps = NULL; // list of static lightmap for this seg seg->lightmaps = NULL; // list of static lightmap for this seg
#endif #endif
seg->numlights = 0;
seg->rlights = NULL;
seg->polyseg = NULL; seg->polyseg = NULL;
seg->dontrenderme = false; seg->polysector = NULL;
seg->polybackside = false;
} }
static void P_LoadSegs(UINT8 *data) static void P_LoadSegs(UINT8 *data)
...@@ -3387,6 +3388,7 @@ static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype) ...@@ -3387,6 +3388,7 @@ static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype)
mn->y = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); mn->y = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS);
mn->dx = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); mn->dx = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS);
mn->dy = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); mn->dy = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS);
mn->length = FixedHypot(mn->dx>>1, mn->dy>>1)<<1;
// Bounding boxes // Bounding boxes
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
...@@ -7692,6 +7694,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) ...@@ -7692,6 +7694,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
Z_Free(ss->attachedsolid); Z_Free(ss->attachedsolid);
} }
Polyobj_ClearAllSubsectorLinks();
NodeBuilder_Clear();
// Clear pointers that would be left dangling by the purge // Clear pointers that would be left dangling by the purge
R_FlushTranslationColormapCache(); R_FlushTranslationColormapCache();
......
...@@ -23,11 +23,16 @@ ...@@ -23,11 +23,16 @@
#include "z_zone.h" // Check R_Prep3DFloors #include "z_zone.h" // Check R_Prep3DFloors
#include "taglist.h" #include "taglist.h"
#include "nodebuilder.h"
seg_t *curline; seg_t *curline;
side_t *sidedef; side_t *sidedef;
line_t *linedef; line_t *linedef;
sector_t *frontsector; sector_t *frontsector;
sector_t *backsector; sector_t *backsector;
polynode_t *polynodes;
static minibsp_t *minibsp = NULL;
// very ugly realloc() of drawsegs at run-time, I upped it to 512 // very ugly realloc() of drawsegs at run-time, I upped it to 512
// instead of 256.. and someone managed to send me a level with // instead of 256.. and someone managed to send me a level with
...@@ -388,23 +393,17 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back) ...@@ -388,23 +393,17 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
// //
static void R_AddLine(seg_t *line) static void R_AddLine(seg_t *line)
{ {
INT32 x1, x2;
angle_t angle1, angle2, span, tspan;
static sector_t tempsec; static sector_t tempsec;
boolean bothceilingssky = false, bothfloorssky = false; boolean bothceilingssky = false, bothfloorssky = false;
portalline = false; angle_t angle1 = R_PointToAngle64(line->v1->x, line->v1->y);
angle_t angle2 = R_PointToAngle64(line->v2->x, line->v2->y);
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return;
// big room fix
angle1 = R_PointToAngle64(line->v1->x, line->v1->y);
angle2 = R_PointToAngle64(line->v2->x, line->v2->y);
curline = line; curline = line;
portalline = false;
// Clip to view edges. // Clip to view edges.
span = angle1 - angle2; angle_t span = angle1 - angle2;
// Back side? i.e. backface culling? // Back side? i.e. backface culling?
if (span >= ANGLE_180) if (span >= ANGLE_180)
...@@ -415,7 +414,7 @@ static void R_AddLine(seg_t *line) ...@@ -415,7 +414,7 @@ static void R_AddLine(seg_t *line)
angle1 -= viewangle; angle1 -= viewangle;
angle2 -= viewangle; angle2 -= viewangle;
tspan = angle1 + clipangle; angle_t tspan = angle1 + clipangle;
if (tspan > doubleclipangle) if (tspan > doubleclipangle)
{ {
tspan -= doubleclipangle; tspan -= doubleclipangle;
...@@ -441,8 +440,9 @@ static void R_AddLine(seg_t *line) ...@@ -441,8 +440,9 @@ static void R_AddLine(seg_t *line)
// The seg is in the view range, but not necessarily visible. // The seg is in the view range, but not necessarily visible.
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT;
x1 = viewangletox[angle1];
x2 = viewangletox[angle2]; INT32 x1 = viewangletox[angle1];
INT32 x2 = viewangletox[angle2];
// Does not cross a pixel? // Does not cross a pixel?
if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness
...@@ -655,6 +655,70 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) ...@@ -655,6 +655,70 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
return true; return true;
} }
static NodeBuilder *PolyNodeBuilder = NULL;
void R_BuildPolyBSP(subsector_t *sub)
{
polynode_t *pn;
UINT32 i;
if (PolyNodeBuilder == NULL)
PolyNodeBuilder = Z_Calloc(sizeof(NodeBuilder), PU_STATIC, NULL);
NodeBuilder_Set(PolyNodeBuilder);
NodeBuilder_Clear();
// Feed segs to the nodebuilder and build the nodes.
NodeBuilder_AddSegs(&segs[sub->firstline], sub->numlines);
for (pn = sub->polynodes; pn != NULL; pn = pn->pnext)
{
NodeBuilder_AddPolySegs(pn);
ps_numpolyobjects.value.i++; // for render stats
}
NodeBuilder_BuildMini();
if (sub->BSP == NULL)
sub->BSP = Z_Calloc(sizeof(minibsp_t), PU_LEVEL, NULL);
NodeBuilder_ExtractMini(sub->BSP);
for (i = 0; i < sub->BSP->numsubsectors; ++i)
{
subsector_t *minisub = &sub->BSP->subsectors[i];
seg_t *line = &sub->BSP->segs[minisub->firstline];
INT32 count = minisub->numlines;
while (count--)
{
if (line->polyseg)
{
minisub->polynodes = sub->polynodes;
break;
}
line++;
}
minisub->sector = sub->sector;
}
}
static void R_AddPolyobjs(subsector_t *sub)
{
INT32 nodecount;
if (sub->BSP == NULL || sub->BSP->dirty)
R_BuildPolyBSP(sub);
minibsp = sub->BSP;
nodecount = minibsp->numnodes - 1;
if (nodecount == 0)
R_Subsector(0);
else
R_RenderMiniBSPNode(nodecount);
minibsp = NULL;
}
size_t numpolys; // number of polyobjects in current subsector size_t numpolys; // number of polyobjects in current subsector
size_t num_po_ptrs; // number of polyobject pointers allocated size_t num_po_ptrs; // number of polyobject pointers allocated
polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
...@@ -719,109 +783,6 @@ void R_SortPolyObjects(subsector_t *sub) ...@@ -719,109 +783,6 @@ void R_SortPolyObjects(subsector_t *sub)
} }
} }
//
// R_PolysegCompare
//
// Callback for qsort to sort the segs of a polyobject. Returns such that the
// closer one is sorted first. I sure hope this doesn't break anything. -Red
//
static int R_PolysegCompare(const void *p1, const void *p2)
{
const seg_t *seg1 = *(const seg_t * const *)p1;
const seg_t *seg2 = *(const seg_t * const *)p2;
fixed_t dist1v1, dist1v2, dist2v1, dist2v2;
// TODO might be a better way to get distance?
#define pdist(x, y) (FixedMul(R_PointToDist(x, y), FINECOSINE((R_PointToAngle(x, y)-viewangle)>>ANGLETOFINESHIFT))+0xFFFFFFF)
#define vxdist(v) pdist(v->x, v->y)
dist1v1 = vxdist(seg1->v1);
dist1v2 = vxdist(seg1->v2);
dist2v1 = vxdist(seg2->v1);
dist2v2 = vxdist(seg2->v2);
if (min(dist1v1, dist1v2) != min(dist2v1, dist2v2))
return min(dist1v1, dist1v2) - min(dist2v1, dist2v2);
{ // That didn't work, so now let's try this.......
fixed_t delta1, delta2, x1, y1, x2, y2;
vertex_t *near1, *near2, *far1, *far2; // wherever you are~
delta1 = R_PointToDist2(seg1->v1->x, seg1->v1->y, seg1->v2->x, seg1->v2->y);
delta2 = R_PointToDist2(seg2->v1->x, seg2->v1->y, seg2->v2->x, seg2->v2->y);
delta1 = FixedDiv(128<<FRACBITS, delta1);
delta2 = FixedDiv(128<<FRACBITS, delta2);
if (dist1v1 < dist1v2)
{
near1 = seg1->v1;
far1 = seg1->v2;
}
else
{
near1 = seg1->v2;
far1 = seg1->v1;
}
if (dist2v1 < dist2v2)
{
near2 = seg2->v1;
far2 = seg2->v2;
}
else
{
near2 = seg2->v2;
far2 = seg2->v1;
}
x1 = near1->x + FixedMul(far1->x-near1->x, delta1);
y1 = near1->y + FixedMul(far1->y-near1->y, delta1);
x2 = near2->x + FixedMul(far2->x-near2->x, delta2);
y2 = near2->y + FixedMul(far2->y-near2->y, delta2);
return pdist(x1, y1)-pdist(x2, y2);
}
#undef vxdist
#undef pdist
}
//
// R_AddPolyObjects
//
// haleyjd 02/19/06
// Adds all segs in all polyobjects in the given subsector.
//
static void R_AddPolyObjects(subsector_t *sub)
{
polyobj_t *po = sub->polyList;
size_t i, j;
numpolys = 0;
// count polyobjects
while (po)
{
++numpolys;
po = (polyobj_t *)(po->link.next);
}
// for render stats
ps_numpolyobjects.value.i += numpolys;
// sort polyobjects
R_SortPolyObjects(sub);
// render polyobjects
for (i = 0; i < numpolys; ++i)
{
qsort(po_ptrs[i]->segs, po_ptrs[i]->segCount, sizeof(seg_t *), R_PolysegCompare);
for (j = 0; j < po_ptrs[i]->segCount; ++j)
R_AddLine(po_ptrs[i]->segs[j]);
}
}
// //
// R_Subsector // R_Subsector
// Determine floor/ceiling planes. // Determine floor/ceiling planes.
...@@ -831,7 +792,7 @@ static void R_AddPolyObjects(subsector_t *sub) ...@@ -831,7 +792,7 @@ static void R_AddPolyObjects(subsector_t *sub)
drawseg_t *firstseg; drawseg_t *firstseg;
static void R_Subsector(size_t num) void R_Subsector(size_t num)
{ {
INT32 count, floorlightlevel, ceilinglightlevel, light; INT32 count, floorlightlevel, ceilinglightlevel, light;
seg_t *line; seg_t *line;
...@@ -842,19 +803,45 @@ static void R_Subsector(size_t num) ...@@ -842,19 +803,45 @@ static void R_Subsector(size_t num)
fixed_t floorcenterz, ceilingcenterz; fixed_t floorcenterz, ceilingcenterz;
ffloor_t *rover; ffloor_t *rover;
if (minibsp)
{
size_t numsubsecs = minibsp->numsubsectors;
if (num >= numsubsecs)
{
#ifdef RANGECHECK #ifdef RANGECHECK
if (num >= numsubsectors) I_Error("R_Subsector: ss %s with numss = %s (miniBSP)\n", sizeu1(num), sizeu2(numsubsecs));
I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
#endif #endif
return;
}
// subsectors added at run-time sub = &minibsp->subsectors[num];
if (num >= numsubsectors) line = &minibsp->segs[sub->firstline];
return; }
else
{
size_t numsubsecs = numsubsectors;
if (num >= numsubsecs) // subsectors added at run-time
{
#ifdef RANGECHECK
I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsecs));
#endif
return;
}
sub = &subsectors[num];
// Render the minibsp instead
if (sub->polynodes)
{
R_AddPolyobjs(sub);
return;
}
line = &segs[sub->firstline];
}
sub = &subsectors[num];
frontsector = sub->sector; frontsector = sub->sector;
count = sub->numlines; count = sub->numlines;
line = &segs[sub->firstline];
// Deep water/fake ceiling effect. // Deep water/fake ceiling effect.
frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); frontsector = R_FakeFlat(frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false);
...@@ -1008,23 +995,19 @@ static void R_Subsector(size_t num) ...@@ -1008,23 +995,19 @@ static void R_Subsector(size_t num)
} }
// Polyobjects have planes, too! // Polyobjects have planes, too!
if (sub->polyList) polynodes = sub->polynodes;
if (minibsp && polynodes)
{ {
polyobj_t *po = sub->polyList; polynode_t *pn = polynodes;
sector_t *polysec;
while (po) for (; pn != NULL && numffloors < MAXFFLOORS; pn = pn->pnext)
{ {
if (numffloors >= MAXFFLOORS) polyobj_t *po = pn->poly;
break;
if (!(po->flags & POF_RENDERPLANES)) // Don't draw planes if (!(po->flags & POF_RENDERPLANES)) // Don't draw planes
{
po = (polyobj_t *)(po->link.next);
continue; continue;
}
polysec = po->lines[0]->backsector; sector_t *polysec = po->lines[0]->backsector;
ffloor[numffloors].plane = NULL; ffloor[numffloors].plane = NULL;
if (polysec->floorheight <= ceilingcenterz if (polysec->floorheight <= ceilingcenterz
...@@ -1036,13 +1019,11 @@ static void R_Subsector(size_t num) ...@@ -1036,13 +1019,11 @@ static void R_Subsector(size_t num)
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs, (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs,
polysec->floorpic_angle-po->angle, polysec->floorpic_angle-po->angle,
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
NULL); // will ffloors be slopable eventually? NULL); // will polyobjects be slopable eventually?
ffloor[numffloors].height = polysec->floorheight; ffloor[numffloors].height = polysec->floorheight;
ffloor[numffloors].polyobj = po; ffloor[numffloors].polyobj = po;
ffloor[numffloors].slope = NULL; ffloor[numffloors].slope = NULL;
//ffloor[numffloors].ffloor = rover;
po->visplane = ffloor[numffloors].plane;
numffloors++; numffloors++;
} }
...@@ -1059,48 +1040,41 @@ static void R_Subsector(size_t num) ...@@ -1059,48 +1040,41 @@ static void R_Subsector(size_t num)
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic, ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle, (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle,
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
NULL); // will ffloors be slopable eventually? NULL); // will polyobjects be slopable eventually?
ffloor[numffloors].polyobj = po; ffloor[numffloors].polyobj = po;
ffloor[numffloors].height = polysec->ceilingheight; ffloor[numffloors].height = polysec->ceilingheight;
ffloor[numffloors].slope = NULL; ffloor[numffloors].slope = NULL;
//ffloor[numffloors].ffloor = rover;
po->visplane = ffloor[numffloors].plane;
numffloors++; numffloors++;
} }
po = (polyobj_t *)(po->link.next);
} }
} }
// killough 9/18/98: Fix underwater slowdown, by passing real sector // killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite // instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area. // lightlevels on floor & ceiling lightlevels in the surrounding area.
// //
// 10/98 killough: // 10/98 killough:
// //
// NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!! // NOTE: TeamTNT fixed this bug incorrectly, messing up sprite lighting!!!
// That is part of the 242 effect!!! If you simply pass sub->sector to // That is part of the 242 effect!!! If you simply pass sub->sector to
// the old code you will not get correct lighting for underwater sprites!!! // the old code you will not get correct lighting for underwater sprites!!!
// Either you must pass the fake sector and handle validcount here, on the // Either you must pass the fake sector and handle validcount here, on the
// real sector, or you must account for the lighting in some other way, // real sector, or you must account for the lighting in some other way,
// like passing it as an argument. // like passing it as an argument.
R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2); R_AddSprites(sub->sector, (floorlightlevel+ceilinglightlevel)/2);
firstseg = NULL; firstseg = NULL;
// haleyjd 02/19/06: draw polyobjects before static lines
if (sub->polyList)
R_AddPolyObjects(sub);
while (count--) while (count--)
{ {
// CONS_Debug(DBG_GAMELOGIC, "Adding normal line %d...(%d)\n", line->linedef-lines, leveltime); if (!line->glseg && !(line->polyseg && !minibsp)) // ignore segs that belong to polyobjects
if (!line->glseg && !line->polyseg) // ignore segs that belong to polyobjects
R_AddLine(line); R_AddLine(line);
line++; line++;
curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so stuff doesn't try using it for other things */ curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so stuff doesn't try using it for other things */
} }
polynodes = NULL;
} }
// //
...@@ -1267,11 +1241,11 @@ void R_RenderBSPNode(INT32 bspnum) ...@@ -1267,11 +1241,11 @@ void R_RenderBSPNode(INT32 bspnum)
// Decide which side the view point is on. // Decide which side the view point is on.
side = R_PointOnSide(viewx, viewy, bsp); side = R_PointOnSide(viewx, viewy, bsp);
// Recursively divide front space. // Recursively divide front space.
R_RenderBSPNode(bsp->children[side]); R_RenderBSPNode(bsp->children[side]);
// Possibly divide back space. // Possibly divide back space.
if (!R_CheckBBox(bsp->bbox[side^1])) if (!R_CheckBBox(bsp->bbox[side^1]))
return; return;
...@@ -1288,3 +1262,30 @@ void R_RenderBSPNode(INT32 bspnum) ...@@ -1288,3 +1262,30 @@ void R_RenderBSPNode(INT32 bspnum)
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR); R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
} }
void R_RenderMiniBSPNode(INT32 bspnum)
{
node_t *bsp;
INT32 side;
ps_numbspcalls.value.i++;
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{
bsp = &minibsp->nodes[bspnum];
// Decide which side the view point is on.
side = R_PointOnSide(viewx, viewy, bsp);
// Recursively divide front space.
R_RenderMiniBSPNode(bsp->children[side]);
// Possibly divide back space.
if (!R_CheckBBox(bsp->bbox[side^1]))
return;
bspnum = bsp->children[side^1];
}
R_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
}
...@@ -23,6 +23,7 @@ extern side_t *sidedef; ...@@ -23,6 +23,7 @@ extern side_t *sidedef;
extern line_t *linedef; extern line_t *linedef;
extern sector_t *frontsector; extern sector_t *frontsector;
extern sector_t *backsector; extern sector_t *backsector;
extern polynode_t *polynodes;
extern boolean portalline; // is curline a portal seg? extern boolean portalline; // is curline a portal seg?
// drawsegs are allocated on the fly... see r_segs.c // drawsegs are allocated on the fly... see r_segs.c
...@@ -38,7 +39,11 @@ extern INT32 doorclosed; ...@@ -38,7 +39,11 @@ extern INT32 doorclosed;
void R_ClearClipSegs(void); void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end); void R_PortalClearClipSegs(INT32 start, INT32 end);
void R_ClearDrawSegs(void); void R_ClearDrawSegs(void);
void R_Subsector(size_t num);
void R_RenderBSPNode(INT32 bspnum); void R_RenderBSPNode(INT32 bspnum);
void R_RenderMiniBSPNode(INT32 bspnum);
void R_BuildPolyBSP(subsector_t *sub);
void R_SortPolyObjects(subsector_t *sub); void R_SortPolyObjects(subsector_t *sub);
......
...@@ -577,6 +577,8 @@ typedef struct ...@@ -577,6 +577,8 @@ typedef struct
extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors. extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors.
} side_t; } side_t;
struct minibsp_s;
// //
// A subsector. // A subsector.
// References a sector. // References a sector.
...@@ -588,8 +590,12 @@ typedef struct subsector_s ...@@ -588,8 +590,12 @@ typedef struct subsector_s
sector_t *sector; sector_t *sector;
INT16 numlines; INT16 numlines;
UINT32 firstline; UINT32 firstline;
struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects
size_t validcount; size_t validcount;
struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects
struct minibsp_s *BSP;
struct polynode_s *polynodes;
} subsector_t; } subsector_t;
// Sector list node showing all sectors an object appears in. // Sector list node showing all sectors an object appears in.
...@@ -663,6 +669,7 @@ typedef struct seg_s ...@@ -663,6 +669,7 @@ typedef struct seg_s
INT32 side; INT32 side;
fixed_t length; // precalculated seg length
fixed_t offset; fixed_t offset;
angle_t angle; angle_t angle;
...@@ -675,7 +682,6 @@ typedef struct seg_s ...@@ -675,7 +682,6 @@ typedef struct seg_s
sector_t *frontsector; sector_t *frontsector;
sector_t *backsector; sector_t *backsector;
fixed_t length; // precalculated seg length
#ifdef HWRENDER #ifdef HWRENDER
// new pointers so that AdjustSegs doesn't mess with v1/v2 // new pointers so that AdjustSegs doesn't mess with v1/v2
void *pv1; // polyvertex_t void *pv1; // polyvertex_t
...@@ -685,11 +691,10 @@ typedef struct seg_s ...@@ -685,11 +691,10 @@ typedef struct seg_s
lightmap_t *lightmaps; // for static lightmap lightmap_t *lightmaps; // for static lightmap
#endif #endif
// Why slow things down by calculating lightlists for every thick side?
size_t numlights;
r_lightlist_t *rlights;
polyobj_t *polyseg; polyobj_t *polyseg;
boolean dontrenderme; sector_t *polysector;
boolean polybackside;
boolean glseg; boolean glseg;
} seg_t; } seg_t;
...@@ -701,14 +706,31 @@ typedef struct ...@@ -701,14 +706,31 @@ typedef struct
// Partition line. // Partition line.
fixed_t x, y; fixed_t x, y;
fixed_t dx, dy; fixed_t dx, dy;
fixed_t length;
// Bounding box for each child. // Bounding box for each child.
fixed_t bbox[2][4]; fixed_t bbox[2][4];
// If NF_SUBSECTOR its a subsector. // If NF_SUBSECTOR, it's a subsector.
UINT16 children[2]; UINT16 children[2];
} node_t; } node_t;
// An entire BSP tree.
typedef struct minibsp_s
{
boolean dirty;
node_t *nodes;
seg_t *segs;
subsector_t *subsectors;
vertex_t *verts;
size_t numnodes;
size_t numsegs;
size_t numsubsectors;
size_t numverts;
} minibsp_t;
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma pack(1) #pragma pack(1)
#endif #endif
......
...@@ -1496,6 +1496,8 @@ void R_RenderPlayerView(player_t *player) ...@@ -1496,6 +1496,8 @@ void R_RenderPlayerView(player_t *player)
#endif #endif
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0; ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
PS_START_TIMING(ps_bsptime); PS_START_TIMING(ps_bsptime);
// Link the polyobjects right before drawing the scene to reduce the amounts of calls to this function
Polyobj_LinkToSubsectors();
R_RenderBSPNode((INT32)numnodes - 1); R_RenderBSPNode((INT32)numnodes - 1);
PS_STOP_TIMING(ps_bsptime); PS_STOP_TIMING(ps_bsptime);
ps_numsprites.value.i = visspritecount; ps_numsprites.value.i = visspritecount;
......
...@@ -492,6 +492,42 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, ...@@ -492,6 +492,42 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
return check; return check;
} }
static visplane_t *R_CreateVisplane(visplane_t *pl, INT32 start, INT32 stop)
{
visplane_t *new_pl;
if (pl->ffloor || pl->polyobj)
{
new_pl = new_visplane(MAXVISPLANES - 1);
}
else
{
unsigned hash =
visplane_hash(pl->picnum, pl->lightlevel, pl->height);
new_pl = new_visplane(hash);
}
new_pl->height = pl->height;
new_pl->picnum = pl->picnum;
new_pl->lightlevel = pl->lightlevel;
new_pl->xoffs = pl->xoffs;
new_pl->yoffs = pl->yoffs;
new_pl->extra_colormap = pl->extra_colormap;
new_pl->ffloor = pl->ffloor;
new_pl->viewx = pl->viewx;
new_pl->viewy = pl->viewy;
new_pl->viewz = pl->viewz;
new_pl->viewangle = pl->viewangle;
new_pl->plangle = pl->plangle;
new_pl->polyobj = pl->polyobj;
new_pl->slope = pl->slope;
new_pl->minx = start;
new_pl->maxx = stop;
memset(new_pl->top, 0xff, sizeof new_pl->top);
memset(new_pl->bottom, 0x00, sizeof new_pl->bottom);
return new_pl;
}
// //
// R_CheckPlane: return same visplane or alloc a new one if needed // R_CheckPlane: return same visplane or alloc a new one if needed
// //
...@@ -501,6 +537,9 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) ...@@ -501,6 +537,9 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
INT32 unionl, unionh; INT32 unionl, unionh;
INT32 x; INT32 x;
if (pl->polyobj)
return R_CreateVisplane(pl, start, stop);
if (start < pl->minx) if (start < pl->minx)
{ {
intrl = pl->minx; intrl = pl->minx;
...@@ -532,45 +571,13 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) ...@@ -532,45 +571,13 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
{ {
pl->minx = unionl; pl->minx = unionl;
pl->maxx = unionh; pl->maxx = unionh;
return pl;
} }
else /* Cannot use existing plane; create a new one */
{
visplane_t *new_pl;
if (pl->ffloor)
{
new_pl = new_visplane(MAXVISPLANES - 1);
}
else
{
unsigned hash =
visplane_hash(pl->picnum, pl->lightlevel, pl->height);
new_pl = new_visplane(hash);
}
new_pl->height = pl->height; /* Cannot use existing plane; create a new one */
new_pl->picnum = pl->picnum; return R_CreateVisplane(pl, start, stop);
new_pl->lightlevel = pl->lightlevel;
new_pl->xoffs = pl->xoffs;
new_pl->yoffs = pl->yoffs;
new_pl->extra_colormap = pl->extra_colormap;
new_pl->ffloor = pl->ffloor;
new_pl->viewx = pl->viewx;
new_pl->viewy = pl->viewy;
new_pl->viewz = pl->viewz;
new_pl->viewangle = pl->viewangle;
new_pl->plangle = pl->plangle;
new_pl->polyobj = pl->polyobj;
new_pl->slope = pl->slope;
pl = new_pl;
pl->minx = start;
pl->maxx = stop;
memset(pl->top, 0xff, sizeof pl->top);
memset(pl->bottom, 0x00, sizeof pl->bottom);
}
return pl;
} }
// //
// R_ExpandPlane // R_ExpandPlane
// //
......
...@@ -136,17 +136,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -136,17 +136,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
void (*colfunc_2s)(column_t *); void (*colfunc_2s)(column_t *);
line_t *ldef; line_t *ldef;
sector_t *front, *back; sector_t *front, *back;
INT32 times, repeats; INT32 times, repeats = 1;
INT64 overflow_test; INT64 overflow_test;
INT32 range; INT32 range;
// Calculate light table.
// Use different light tables
// for horizontal / vertical / diagonal. Diagonal?
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
curline = ds->curline; curline = ds->curline;
frontsector = curline->frontsector; frontsector = curline->polyseg ? curline->polysector : curline->frontsector;
backsector = curline->backsector; backsector = curline->backsector;
texnum = R_GetTextureNum(curline->sidedef->midtexture); texnum = R_GetTextureNum(curline->sidedef->midtexture);
windowbottom = windowtop = sprbotscreen = INT32_MAX; windowbottom = windowtop = sprbotscreen = INT32_MAX;
...@@ -236,8 +232,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -236,8 +232,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
rlight->height = (centeryfrac) - FixedMul(leftheight , ds->scale1); rlight->height = (centeryfrac) - FixedMul(leftheight , ds->scale1);
rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2); rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2);
rlight->heightstep = (rlight->heightstep-rlight->height)/(range); rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
//if (x1 > ds->x1)
//rlight->height -= (x1 - ds->x1)*rlight->heightstep;
rlight->startheight = rlight->height; // keep starting value here to reset for each repeat rlight->startheight = rlight->height; // keep starting value here to reset for each repeat
rlight->lightlevel = *light->lightlevel; rlight->lightlevel = *light->lightlevel;
rlight->extra_colormap = *light->extra_colormap; rlight->extra_colormap = *light->extra_colormap;
...@@ -262,6 +256,10 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -262,6 +256,10 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
} }
else else
{ {
// Calculate light table.
// Use different light tables
// for horizontal / vertical / diagonal. Diagonal?
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
...@@ -299,28 +297,29 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -299,28 +297,29 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
else else
back = backsector; back = backsector;
if (ds->curline->sidedef->repeatcnt) if (!curline->polyseg)
repeats = 1 + ds->curline->sidedef->repeatcnt;
else if (ldef->flags & ML_WRAPMIDTEX)
{ {
fixed_t high, low; if (ds->curline->sidedef->repeatcnt)
repeats = 1 + ds->curline->sidedef->repeatcnt;
else if (ldef->flags & ML_WRAPMIDTEX)
{
fixed_t high, low;
if (front->ceilingheight > back->ceilingheight) if (front->ceilingheight > back->ceilingheight)
high = back->ceilingheight; high = back->ceilingheight;
else else
high = front->ceilingheight; high = front->ceilingheight;
if (front->floorheight > back->floorheight) if (front->floorheight > back->floorheight)
low = front->floorheight; low = front->floorheight;
else else
low = back->floorheight; low = back->floorheight;
repeats = (high - low)/textureheight[texnum]; repeats = (high - low)/textureheight[texnum];
if ((high-low)%textureheight[texnum]) if ((high-low)%textureheight[texnum])
repeats++; // tile an extra time to fill the gap -- Monster Iestyn repeats++; // tile an extra time to fill the gap -- Monster Iestyn
}
} }
else
repeats = 1;
for (times = 0; times < repeats; times++) for (times = 0; times < repeats; times++)
{ {
...@@ -459,7 +458,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -459,7 +458,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red #if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red
if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) if (curline->polybackside && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES))
{ {
fixed_t my_topscreen; fixed_t my_topscreen;
fixed_t my_bottomscreen; fixed_t my_bottomscreen;
...@@ -1154,7 +1153,7 @@ static void R_RenderSegLoop (void) ...@@ -1154,7 +1153,7 @@ static void R_RenderSegLoop (void)
for (i = 0; i < numffloors; i++) for (i = 0; i < numffloors; i++)
{ {
if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg)) if (ffloor[i].polyobj && ffloor[i].polyobj != curline->polyseg)
continue; continue;
if (ffloor[i].height < viewz) if (ffloor[i].height < viewz)
...@@ -1174,33 +1173,30 @@ static void R_RenderSegLoop (void) ...@@ -1174,33 +1173,30 @@ static void R_RenderSegLoop (void)
ffloor[i].plane->top[rw_x] = 0xFFFF; ffloor[i].plane->top[rw_x] = 0xFFFF;
ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
} }
else else if (top_w <= bottom_w)
{ {
if (top_w <= bottom_w) fftop = (INT16)top_w;
{ ffbottom = (INT16)bottom_w;
fftop = (INT16)top_w;
ffbottom = (INT16)bottom_w;
ffloor[i].plane->top[rw_x] = fftop; ffloor[i].plane->top[rw_x] = fftop;
ffloor[i].plane->bottom[rw_x] = ffbottom; ffloor[i].plane->bottom[rw_x] = ffbottom;
// Lactozilla: Cull part of the column by the 3D floor if it can't be seen // Lactozilla: Cull part of the column by the 3D floor if it can't be seen
// "bottom" is the top pixel of the floor column // "bottom" is the top pixel of the floor column
if (ffbottom >= bottom-1 && R_FFloorCanClip(&ffloor[i]) && !curline->polyseg) if (ffbottom >= bottom-1 && R_FFloorCanClip(&ffloor[i]) && !curline->polyseg)
{ {
rw_floormarked = true; rw_floormarked = true;
floorclip[rw_x] = fftop; floorclip[rw_x] = fftop;
if (yh > fftop) if (yh > fftop)
yh = fftop; yh = fftop;
if (markfloor && floorplane) if (markfloor && floorplane)
floorplane->top[rw_x] = bottom; floorplane->top[rw_x] = bottom;
if (rw_silhouette) if (rw_silhouette)
{ {
(*rw_silhouette) |= SIL_BOTTOM; (*rw_silhouette) |= SIL_BOTTOM;
(*rw_bsilheight) = INT32_MAX; (*rw_bsilheight) = INT32_MAX;
}
} }
} }
} }
...@@ -1222,33 +1218,30 @@ static void R_RenderSegLoop (void) ...@@ -1222,33 +1218,30 @@ static void R_RenderSegLoop (void)
ffloor[i].plane->top[rw_x] = 0xFFFF; ffloor[i].plane->top[rw_x] = 0xFFFF;
ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
} }
else else if (top_w <= bottom_w)
{ {
if (top_w <= bottom_w) fftop = (INT16)top_w;
{ ffbottom = (INT16)bottom_w;
fftop = (INT16)top_w;
ffbottom = (INT16)bottom_w;
ffloor[i].plane->top[rw_x] = fftop; ffloor[i].plane->top[rw_x] = fftop;
ffloor[i].plane->bottom[rw_x] = ffbottom; ffloor[i].plane->bottom[rw_x] = ffbottom;
// Lactozilla: Cull part of the column by the 3D floor if it can't be seen // Lactozilla: Cull part of the column by the 3D floor if it can't be seen
// "top" is the height of the ceiling column // "top" is the height of the ceiling column
if (fftop <= top+1 && R_FFloorCanClip(&ffloor[i]) && !curline->polyseg) if (fftop <= top+1 && R_FFloorCanClip(&ffloor[i]) && !curline->polyseg)
{ {
rw_ceilingmarked = true; rw_ceilingmarked = true;
ceilingclip[rw_x] = ffbottom; ceilingclip[rw_x] = ffbottom;
if (yl < ffbottom) if (yl < ffbottom)
yl = ffbottom; yl = ffbottom;
if (markceiling && ceilingplane) if (markceiling && ceilingplane)
ceilingplane->bottom[rw_x] = top; ceilingplane->bottom[rw_x] = top;
if (rw_silhouette) if (rw_silhouette)
{ {
(*rw_silhouette) |= SIL_TOP; (*rw_silhouette) |= SIL_TOP;
(*rw_tsilheight) = INT32_MIN; (*rw_tsilheight) = INT32_MIN;
}
} }
} }
} }
...@@ -1277,7 +1270,7 @@ static void R_RenderSegLoop (void) ...@@ -1277,7 +1270,7 @@ static void R_RenderSegLoop (void)
// calculate lighting // calculate lighting
pindex = FixedMul(rw_scale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; pindex = FixedMul(rw_scale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE) if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1; pindex = MAXLIGHTSCALE-1;
dc_colormap = walllights[pindex]; dc_colormap = walllights[pindex];
...@@ -1461,29 +1454,24 @@ static void R_RenderSegLoop (void) ...@@ -1461,29 +1454,24 @@ static void R_RenderSegLoop (void)
} }
} }
if (dc_numlights) for (i = 0; i < dc_numlights; i++)
{ {
for (i = 0; i < dc_numlights; i++) dc_lightlist[i].height += dc_lightlist[i].heightstep;
{ if (dc_lightlist[i].flags & FOF_CUTSOLIDS)
dc_lightlist[i].height += dc_lightlist[i].heightstep; dc_lightlist[i].botheight += dc_lightlist[i].botheightstep;
if (dc_lightlist[i].flags & FOF_CUTSOLIDS)
dc_lightlist[i].botheight += dc_lightlist[i].botheightstep;
}
} }
for (i = 0; i < numffloors; i++) for (i = 0; i < numffloors; i++)
{ {
if (curline->polyseg && (ffloor[i].polyobj != curline->polyseg)) if (ffloor[i].polyobj && ffloor[i].polyobj != curline->polyseg)
continue; continue;
ffloor[i].f_frac += ffloor[i].f_step; ffloor[i].f_frac += ffloor[i].f_step;
} }
for (i = 0; i < numbackffloors; i++) for (i = 0; i < numbackffloors; i++)
{ {
if (curline->polyseg && (ffloor[i].polyobj != curline->polyseg)) if (ffloor[i].polyobj && ffloor[i].polyobj != curline->polyseg)
continue; continue;
ffloor[i].f_clip[rw_x] = ffloor[i].c_clip[rw_x] = (INT16)((ffloor[i].b_frac >> HEIGHTBITS) & 0xFFFF); ffloor[i].f_clip[rw_x] = ffloor[i].c_clip[rw_x] = (INT16)((ffloor[i].b_frac >> HEIGHTBITS) & 0xFFFF);
ffloor[i].b_frac += ffloor[i].b_step; ffloor[i].b_frac += ffloor[i].b_step;
} }
...@@ -1726,16 +1714,10 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -1726,16 +1714,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
for (i = 0; i < MAXFFLOORS; i++) for (i = 0; i < MAXFFLOORS; i++)
ds_p->thicksides[i] = NULL; ds_p->thicksides[i] = NULL;
if (numffloors) for (i = 0; i < numffloors; i++)
{ {
for (i = 0; i < numffloors; i++) ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft .x, segleft .y, ffloor[i].height) - viewz;
{ ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y, ffloor[i].height) - viewz;
if (ffloor[i].polyobj && (!ds_p->curline->polyseg || ffloor[i].polyobj != ds_p->curline->polyseg))
continue;
ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft .x, segleft .y, ffloor[i].height) - viewz;
ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y, ffloor[i].height) - viewz;
}
} }
// Set up texture Y offset slides for sloped walls // Set up texture Y offset slides for sloped walls
...@@ -2026,17 +2008,16 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2026,17 +2008,16 @@ void R_StoreWallRange(INT32 start, INT32 stop)
rw_bottomtexturemid += sidedef->rowoffset; rw_bottomtexturemid += sidedef->rowoffset;
// allocate space for masked texture tables // allocate space for masked texture tables
if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) if (backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors))
{ {
ffloor_t *rover; ffloor_t *rover;
ffloor_t *r2; ffloor_t *r2;
fixed_t lowcut, highcut; fixed_t lowcut, highcut;
fixed_t lowcutslope, highcutslope; fixed_t lowcutslope, highcutslope;
// Used for height comparisons and etc across FOFs and slopes // Used for height comparisons and etc across FOFs and slopes
fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2; fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2;
//markceiling = markfloor = true;
maskedtexture = true; maskedtexture = true;
ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x; ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x;
...@@ -2218,7 +2199,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2218,7 +2199,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
ds_p->numthicksides = numthicksides = i; ds_p->numthicksides = numthicksides = i;
} }
if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures)
if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures
&& !(curline->polyseg && !(curline->polyseg->flags & POF_RENDERSIDES)))
{ {
// masked midtexture // masked midtexture
if (!ds_p->thicksidecol) if (!ds_p->thicksidecol)
...@@ -2229,10 +2212,11 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2229,10 +2212,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else else
ds_p->maskedtexturecol = ds_p->thicksidecol; ds_p->maskedtexturecol = ds_p->thicksidecol;
maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0]) maskedtextureheight = ds_p->maskedtextureheight;
// use REAL front and back floors please, so midtexture rendering isn't mucked up
if (curline->polyseg) if (curline->polyseg)
{ // use REAL front and back floors please, so midtexture rendering isn't mucked up {
rw_midtextureslide = rw_midtexturebackslide = 0; rw_midtextureslide = rw_midtexturebackslide = 0;
if (linedef->flags & ML_MIDPEG) if (linedef->flags & ML_MIDPEG)
rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz; rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz;
...@@ -2445,23 +2429,20 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2445,23 +2429,20 @@ void R_StoreWallRange(INT32 start, INT32 stop)
dc_numlights = p; dc_numlights = p;
} }
if (numffloors) for (i = 0; i < numffloors; i++)
{ {
for (i = 0; i < numffloors; i++) ffloor[i].f_pos >>= 4;
ffloor[i].f_pos_slope >>= 4;
if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too.
{ {
ffloor[i].f_pos >>= 4; ffloor[i].f_step = 0;
ffloor[i].f_pos_slope >>= 4; ffloor[i].f_frac = (centeryfrac>>4);
if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too. topfrac++; // Prevent 1px HOM
{ }
ffloor[i].f_step = 0; else
ffloor[i].f_frac = (centeryfrac>>4); {
topfrac++; // Prevent 1px HOM ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale);
} ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(range);
else
{
ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale);
ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(range);
}
} }
} }
...@@ -2493,11 +2474,13 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2493,11 +2474,13 @@ void R_StoreWallRange(INT32 start, INT32 stop)
} }
} }
i = 0;
if (backsector->ffloors || frontsector->ffloors)
{ {
ffloor_t * rover; ffloor_t *rover;
fixed_t roverleft, roverright; fixed_t roverleft, roverright;
fixed_t planevistest; fixed_t planevistest;
i = 0;
if (backsector->ffloors) if (backsector->ffloors)
{ {
...@@ -2521,7 +2504,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2521,7 +2504,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
((viewz < planevistest && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || ((viewz < planevistest && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) ||
(viewz > planevistest && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) (viewz > planevistest && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES))))
{ {
//ffloor[i].slope = *rover->b_slope;
ffloor[i].b_pos = roverleft; ffloor[i].b_pos = roverleft;
ffloor[i].b_pos_slope = roverright; ffloor[i].b_pos_slope = roverright;
ffloor[i].b_pos >>= 4; ffloor[i].b_pos >>= 4;
...@@ -2544,7 +2526,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2544,7 +2526,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
((viewz > planevistest && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || ((viewz > planevistest && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) ||
(viewz < planevistest && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) (viewz < planevistest && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES))))
{ {
//ffloor[i].slope = *rover->t_slope;
ffloor[i].b_pos = roverleft; ffloor[i].b_pos = roverleft;
ffloor[i].b_pos_slope = roverright; ffloor[i].b_pos_slope = roverright;
ffloor[i].b_pos >>= 4; ffloor[i].b_pos >>= 4;
...@@ -2556,7 +2537,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2556,7 +2537,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
} }
} }
} }
else if (frontsector && frontsector->ffloors) else if (frontsector->ffloors)
{ {
for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next) for (rover = frontsector->ffloors; rover && i < MAXFFLOORS; rover = rover->next)
{ {
...@@ -2578,7 +2559,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2578,7 +2559,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
((viewz < planevistest && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || ((viewz < planevistest && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) ||
(viewz > planevistest && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) (viewz > planevistest && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES))))
{ {
//ffloor[i].slope = *rover->b_slope;
ffloor[i].b_pos = roverleft; ffloor[i].b_pos = roverleft;
ffloor[i].b_pos_slope = roverright; ffloor[i].b_pos_slope = roverright;
ffloor[i].b_pos >>= 4; ffloor[i].b_pos >>= 4;
...@@ -2601,7 +2581,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2601,7 +2581,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
((viewz > planevistest && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || ((viewz > planevistest && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) ||
(viewz < planevistest && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) (viewz < planevistest && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES))))
{ {
//ffloor[i].slope = *rover->t_slope;
ffloor[i].b_pos = roverleft; ffloor[i].b_pos = roverleft;
ffloor[i].b_pos_slope = roverright; ffloor[i].b_pos_slope = roverright;
ffloor[i].b_pos >>= 4; ffloor[i].b_pos >>= 4;
...@@ -2613,46 +2592,49 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2613,46 +2592,49 @@ void R_StoreWallRange(INT32 start, INT32 stop)
} }
} }
} }
if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES))
polyobj_t *po = curline->polyseg;
if (po && po->flags & POF_RENDERPLANES)
{ {
while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++; sector_t *polysec = po->lines[0]->backsector;
if (i < numffloors && backsector->floorheight <= frontsector->ceilingheight &&
backsector->floorheight >= frontsector->floorheight &&
(viewz < backsector->floorheight))
{
if (ffloor[i].plane->minx > ds_p->x1)
ffloor[i].plane->minx = ds_p->x1;
if (ffloor[i].plane->maxx < ds_p->x2) while (i < numffloors && ffloor[i].polyobj != po) i++;
ffloor[i].plane->maxx = ds_p->x2;
ffloor[i].slope = NULL; if (i < MAXFFLOORS && polysec->floorheight <= frontsector->ceilingheight &&
ffloor[i].b_pos = backsector->floorheight; polysec->floorheight >= frontsector->floorheight &&
(viewz < polysec->floorheight))
{
ffloor[i].b_pos = polysec->floorheight;
ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
i++; i++;
} }
if (i < numffloors && backsector->ceilingheight >= frontsector->floorheight &&
backsector->ceilingheight <= frontsector->ceilingheight &&
(viewz > backsector->ceilingheight))
{
if (ffloor[i].plane->minx > ds_p->x1)
ffloor[i].plane->minx = ds_p->x1;
if (ffloor[i].plane->maxx < ds_p->x2)
ffloor[i].plane->maxx = ds_p->x2;
ffloor[i].slope = NULL; if (i < MAXFFLOORS && polysec->ceilingheight >= frontsector->floorheight &&
ffloor[i].b_pos = backsector->ceilingheight; polysec->ceilingheight <= frontsector->ceilingheight &&
(viewz > polysec->ceilingheight))
{
ffloor[i].b_pos = polysec->ceilingheight;
ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
i++; i++;
} }
} }
}
numbackffloors = i;
}
numbackffloors = i; for (i = 0; i < numffloors; i++)
{
if (curline->polyseg == ffloor[i].polyobj)
{
if (ffloor[i].plane->minx > ds_p->x1)
ffloor[i].plane->minx = ds_p->x1;
if (ffloor[i].plane->maxx < ds_p->x2)
ffloor[i].plane->maxx = ds_p->x2;
} }
} }
...@@ -2704,20 +2686,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2704,20 +2686,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
for (i = 0; i < numffloors; i++) for (i = 0; i < numffloors; i++)
R_ExpandPlane(ffloor[i].plane, rw_x, rw_stopx - 1); R_ExpandPlane(ffloor[i].plane, rw_x, rw_stopx - 1);
} }
// FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red
if (curline->polyseg)
{
for (i = 0; i < numffloors; i++)
{
if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)
continue;
if (ffloor[i].plane->minx > rw_x)
ffloor[i].plane->minx = rw_x;
if (ffloor[i].plane->maxx < rw_stopx - 1)
ffloor[i].plane->maxx = rw_stopx - 1;
}
}
} }
rw_silhouette = &(ds_p->silhouette); rw_silhouette = &(ds_p->silhouette);
......
...@@ -2588,7 +2588,7 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link); ...@@ -2588,7 +2588,7 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link);
static drawnode_t nodebankhead; static drawnode_t nodebankhead;
static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean tempskip) static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head)
{ {
drawnode_t *entry; drawnode_t *entry;
drawseg_t *ds; drawseg_t *ds;
...@@ -2613,21 +2613,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps ...@@ -2613,21 +2613,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
entry->ffloor = ds->thicksides[i]; entry->ffloor = ds->thicksides[i];
} }
} }
// Check for a polyobject plane, but only if this is a front line
if (ds->curline->polyseg && ds->curline->polyseg->visplane && !ds->curline->side) {
plane = ds->curline->polyseg->visplane;
R_PlaneBounds(plane);
if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low)
;
else {
// Put it in!
entry = R_CreateDrawNode(head);
entry->plane = plane;
entry->seg = ds;
}
ds->curline->polyseg->visplane = NULL;
}
if (ds->maskedtexturecol) if (ds->maskedtexturecol)
{ {
entry = R_CreateDrawNode(head); entry = R_CreateDrawNode(head);
...@@ -2646,7 +2631,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps ...@@ -2646,7 +2631,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
plane = ds->ffloorplanes[p]; plane = ds->ffloorplanes[p];
R_PlaneBounds(plane); R_PlaneBounds(plane);
if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low || plane->polyobj) if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low || (plane->polyobj && !ds->curline->side))
{ {
ds->ffloorplanes[p] = NULL; ds->ffloorplanes[p] = NULL;
continue; continue;
...@@ -2672,30 +2657,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps ...@@ -2672,30 +2657,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
} }
} }
if (tempskip)
return;
// find all the remaining polyobject planes and add them on the end of the list
// probably this is a terrible idea if we wanted them to be sorted properly
// but it works getting them in for now
for (i = 0; i < numPolyObjects; i++)
{
if (!PolyObjects[i].visplane)
continue;
plane = PolyObjects[i].visplane;
R_PlaneBounds(plane);
if (plane->low < 0 || plane->high > vid.height || plane->high > plane->low)
{
PolyObjects[i].visplane = NULL;
continue;
}
entry = R_CreateDrawNode(head);
entry->plane = plane;
// note: no seg is set, for what should be obvious reasons
PolyObjects[i].visplane = NULL;
}
// No vissprites in this mask? // No vissprites in this mask?
if (mask->vissprites[1] - mask->vissprites[0] == 0) if (mask->vissprites[1] - mask->vissprites[0] == 0)
return; return;
...@@ -3354,7 +3315,7 @@ void R_DrawMasked(maskcount_t* masks, INT32 nummasks) ...@@ -3354,7 +3315,7 @@ void R_DrawMasked(maskcount_t* masks, INT32 nummasks)
viewz = masks[i].viewz; viewz = masks[i].viewz;
viewsector = masks[i].viewsector; viewsector = masks[i].viewsector;
R_CreateDrawNodes(&masks[i], &heads[i], false); R_CreateDrawNodes(&masks[i], &heads[i]);
} }
//for (i = 0; i < nummasks; i++) //for (i = 0; i < nummasks; i++)
......