2016-09-14 18:01:13 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Copyright(C) 2005-2016 Christoph Oelckers
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with this program. If not, see http://www.gnu.org/licenses/
|
|
|
|
//
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
//
|
2013-06-23 07:49:34 +00:00
|
|
|
/*
|
|
|
|
** gl_setup.cpp
|
|
|
|
** Initializes the data structures required by the GL renderer to handle
|
|
|
|
** a level
|
|
|
|
**
|
2016-09-14 18:01:13 +00:00
|
|
|
**/
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
#include "gl/system/gl_system.h"
|
|
|
|
#include "doomtype.h"
|
|
|
|
#include "colormatcher.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "p_local.h"
|
2016-02-16 21:01:04 +00:00
|
|
|
#include "p_spec.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "p_lnspec.h"
|
|
|
|
#include "c_dispatch.h"
|
|
|
|
#include "r_sky.h"
|
|
|
|
#include "sc_man.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
#include "gi.h"
|
|
|
|
#include "p_setup.h"
|
|
|
|
#include "g_level.h"
|
|
|
|
|
|
|
|
#include "gl/renderer/gl_renderer.h"
|
|
|
|
#include "gl/data/gl_data.h"
|
|
|
|
#include "gl/data/gl_vertexbuffer.h"
|
|
|
|
#include "gl/dynlights/gl_dynlight.h"
|
|
|
|
#include "gl/dynlights/gl_glow.h"
|
|
|
|
#include "gl/utility/gl_clock.h"
|
|
|
|
#include "gl/gl_functions.h"
|
|
|
|
|
|
|
|
void InitGLRMapinfoData();
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
2016-07-27 14:27:40 +00:00
|
|
|
static TArray<subsector_t *> MapSectionCollector;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
static void DoSetMapSection(subsector_t *sub, int num)
|
|
|
|
{
|
2016-07-27 14:27:40 +00:00
|
|
|
MapSectionCollector.Resize(1);
|
|
|
|
MapSectionCollector[0] = sub;
|
2013-06-23 07:49:34 +00:00
|
|
|
sub->mapsection = num;
|
2016-07-27 14:27:40 +00:00
|
|
|
for (unsigned a = 0; a < MapSectionCollector.Size(); a++)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-07-27 14:27:40 +00:00
|
|
|
sub = MapSectionCollector[a];
|
|
|
|
for (DWORD i = 0; i < sub->numlines; i++)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-07-27 14:27:40 +00:00
|
|
|
seg_t * seg = sub->firstline + i;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-07-27 14:27:40 +00:00
|
|
|
if (seg->PartnerSeg)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2016-07-27 14:27:40 +00:00
|
|
|
subsector_t * sub2 = seg->PartnerSeg->Subsector;
|
|
|
|
|
|
|
|
if (sub2->mapsection != num)
|
|
|
|
{
|
|
|
|
assert(sub2->mapsection == 0);
|
|
|
|
sub2->mapsection = num;
|
|
|
|
MapSectionCollector.Push(sub2);
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-27 14:27:40 +00:00
|
|
|
MapSectionCollector.Clear();
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Merge sections. This is needed in case the map contains errors
|
|
|
|
// like overlapping lines resulting in abnormal subsectors.
|
|
|
|
//
|
|
|
|
// This function ensures that any vertex position can only be in one section.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
struct cvertex_t
|
|
|
|
{
|
2016-04-08 10:38:09 +00:00
|
|
|
double X, Y;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-04-08 10:38:09 +00:00
|
|
|
operator int() const { return xs_FloorToInt(X) + 65536 * xs_FloorToInt(Y); }
|
|
|
|
bool operator!= (const cvertex_t &other) const { return fabs(X - other.X) >= EQUAL_EPSILON || fabs(Y - other.Y) >= EQUAL_EPSILON; }
|
|
|
|
cvertex_t& operator =(const vertex_t *v) { X = v->fX(); Y = v->fY(); return *this; }
|
2013-06-23 07:49:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef TMap<cvertex_t, int> FSectionVertexMap;
|
|
|
|
|
|
|
|
static int MergeMapSections(int num)
|
|
|
|
{
|
|
|
|
FSectionVertexMap vmap;
|
|
|
|
FSectionVertexMap::Pair *pair;
|
|
|
|
TArray<int> sectmap;
|
|
|
|
TArray<bool> sectvalid;
|
|
|
|
sectmap.Resize(num);
|
|
|
|
sectvalid.Resize(num);
|
|
|
|
for(int i=0;i<num;i++)
|
|
|
|
{
|
|
|
|
sectmap[i] = -1;
|
|
|
|
sectvalid[i] = true;
|
|
|
|
}
|
|
|
|
int mergecount = 1;
|
|
|
|
|
|
|
|
|
|
|
|
cvertex_t vt;
|
|
|
|
|
|
|
|
// first step: Set mapsection for all vertex positions.
|
2013-08-28 06:33:11 +00:00
|
|
|
for(DWORD i=0;i<(DWORD)numsegs;i++)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
seg_t * seg = &segs[i];
|
|
|
|
int section = seg->Subsector->mapsection;
|
|
|
|
for(int j=0;j<2;j++)
|
|
|
|
{
|
|
|
|
vt = j==0? seg->v1:seg->v2;
|
|
|
|
vmap[vt] = section;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// second step: Check if any seg references more than one mapsection, either by subsector or by vertex
|
2013-08-28 06:33:11 +00:00
|
|
|
for(DWORD i=0;i<(DWORD)numsegs;i++)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
seg_t * seg = &segs[i];
|
|
|
|
int section = seg->Subsector->mapsection;
|
|
|
|
for(int j=0;j<2;j++)
|
|
|
|
{
|
|
|
|
vt = j==0? seg->v1:seg->v2;
|
|
|
|
int vsection = vmap[vt];
|
|
|
|
|
|
|
|
if (vsection != section)
|
|
|
|
{
|
|
|
|
// These 2 sections should be merged
|
|
|
|
for(int k=0;k<numsubsectors;k++)
|
|
|
|
{
|
|
|
|
if (subsectors[k].mapsection == vsection) subsectors[k].mapsection = section;
|
|
|
|
}
|
|
|
|
FSectionVertexMap::Iterator it(vmap);
|
|
|
|
while (it.NextPair(pair))
|
|
|
|
{
|
|
|
|
if (pair->Value == vsection) pair->Value = section;
|
|
|
|
}
|
|
|
|
sectvalid[vsection-1] = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(int i=0;i<num;i++)
|
|
|
|
{
|
|
|
|
if (sectvalid[i]) sectmap[i] = mergecount++;
|
|
|
|
}
|
|
|
|
for(int i=0;i<numsubsectors;i++)
|
|
|
|
{
|
|
|
|
subsectors[i].mapsection = sectmap[subsectors[i].mapsection-1];
|
|
|
|
assert(subsectors[i].mapsection!=-1);
|
|
|
|
}
|
|
|
|
return mergecount-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void SetMapSections()
|
|
|
|
{
|
|
|
|
bool set;
|
|
|
|
int num = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
set = false;
|
|
|
|
for(int i=0; i<numsubsectors; i++)
|
|
|
|
{
|
|
|
|
if (subsectors[i].mapsection == 0)
|
|
|
|
{
|
|
|
|
num++;
|
|
|
|
DoSetMapSection(&subsectors[i], num);
|
|
|
|
set = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (set);
|
|
|
|
num = MergeMapSections(num);
|
|
|
|
currentmapsection.Resize(1 + num/8);
|
|
|
|
#ifdef DEBUG
|
|
|
|
Printf("%d map sections found\n", num);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// prepare subsectors for GL rendering
|
|
|
|
// - analyze rendering hacks using open sectors
|
|
|
|
// - assign a render sector (for self referencing sectors)
|
|
|
|
// - calculate a bounding box
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void SpreadHackedFlag(subsector_t * sub)
|
|
|
|
{
|
|
|
|
// The subsector pointer hasn't been set yet!
|
|
|
|
for(DWORD i=0;i<sub->numlines;i++)
|
|
|
|
{
|
|
|
|
seg_t * seg = sub->firstline + i;
|
|
|
|
|
|
|
|
if (seg->PartnerSeg)
|
|
|
|
{
|
|
|
|
subsector_t * sub2 = seg->PartnerSeg->Subsector;
|
|
|
|
|
|
|
|
if (!(sub2->hacked&1) && sub2->render_sector == sub->render_sector)
|
|
|
|
{
|
|
|
|
sub2->hacked|=1;
|
2014-08-31 21:01:53 +00:00
|
|
|
sub->hacked &= ~4;
|
2013-06-23 07:49:34 +00:00
|
|
|
SpreadHackedFlag (sub2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void PrepareSectorData()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
TArray<subsector_t *> undetermined;
|
|
|
|
subsector_t * ss;
|
|
|
|
|
|
|
|
// now group the subsectors by sector
|
|
|
|
subsector_t ** subsectorbuffer = new subsector_t * [numsubsectors];
|
|
|
|
|
|
|
|
for(i=0, ss=subsectors; i<numsubsectors; i++, ss++)
|
|
|
|
{
|
|
|
|
ss->render_sector->subsectorcount++;
|
|
|
|
}
|
|
|
|
|
2017-01-07 18:32:24 +00:00
|
|
|
for (auto &sec : level.sectors)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2017-01-07 18:32:24 +00:00
|
|
|
sec.subsectors = subsectorbuffer;
|
|
|
|
subsectorbuffer += sec.subsectorcount;
|
|
|
|
sec.subsectorcount = 0;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0, ss = subsectors; i<numsubsectors; i++, ss++)
|
|
|
|
{
|
|
|
|
ss->render_sector->subsectors[ss->render_sector->subsectorcount++]=ss;
|
|
|
|
}
|
|
|
|
|
|
|
|
// marks all malformed subsectors so rendering tricks using them can be handled more easily
|
|
|
|
for (i = 0; i < numsubsectors; i++)
|
|
|
|
{
|
|
|
|
if (subsectors[i].sector == subsectors[i].render_sector)
|
|
|
|
{
|
|
|
|
seg_t * seg = subsectors[i].firstline;
|
|
|
|
for(DWORD j=0;j<subsectors[i].numlines;j++)
|
|
|
|
{
|
|
|
|
if (!(subsectors[i].hacked&1) && seg[j].linedef==0 &&
|
|
|
|
seg[j].PartnerSeg!=NULL &&
|
|
|
|
subsectors[i].render_sector != seg[j].PartnerSeg->Subsector->render_sector)
|
|
|
|
{
|
2016-08-28 08:11:09 +00:00
|
|
|
DPrintf(DMSG_NOTIFY, "Found hack: (%f,%f) (%f,%f)\n", seg[j].v1->fX(), seg[j].v1->fY(), seg[j].v2->fX(), seg[j].v2->fY());
|
2014-08-31 21:01:53 +00:00
|
|
|
subsectors[i].hacked|=5;
|
2013-06-23 07:49:34 +00:00
|
|
|
SpreadHackedFlag(&subsectors[i]);
|
|
|
|
}
|
|
|
|
if (seg[j].PartnerSeg==NULL) subsectors[i].hacked|=2; // used for quick termination checks
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetMapSections();
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Some processing for transparent door hacks using a floor raised by 1 map unit
|
|
|
|
// - This will be used to lower the floor of such sectors by one map unit
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void PrepareTransparentDoors(sector_t * sector)
|
|
|
|
{
|
|
|
|
bool solidwall=false;
|
2017-01-05 13:45:15 +00:00
|
|
|
unsigned int notextures=0;
|
|
|
|
unsigned int nobtextures=0;
|
|
|
|
unsigned int selfref=0;
|
2013-06-23 07:49:34 +00:00
|
|
|
sector_t * nextsec=NULL;
|
|
|
|
|
|
|
|
P_Recalculate3DFloors(sector);
|
|
|
|
if (sector->subsectorcount==0) return;
|
|
|
|
|
|
|
|
sector->transdoorheight=sector->GetPlaneTexZ(sector_t::floor);
|
2016-03-29 11:45:50 +00:00
|
|
|
sector->transdoor= !(sector->e->XFloor.ffloors.Size() || sector->heightsec || sector->floorplane.isSlope());
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
if (sector->transdoor)
|
|
|
|
{
|
2017-01-02 20:40:52 +00:00
|
|
|
for (auto ln : sector->Lines)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2017-01-02 20:40:52 +00:00
|
|
|
if (ln->frontsector == ln->backsector)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
selfref++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-01-02 20:40:52 +00:00
|
|
|
sector_t * sec=getNextSector(ln, sector);
|
2013-06-23 07:49:34 +00:00
|
|
|
if (sec==NULL)
|
|
|
|
{
|
|
|
|
solidwall=true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nextsec=sec;
|
|
|
|
|
2017-01-02 20:40:52 +00:00
|
|
|
int side = ln->sidedef[0]->sector == sec;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2016-06-29 10:19:00 +00:00
|
|
|
if (sector->GetPlaneTexZ(sector_t::floor)!=sec->GetPlaneTexZ(sector_t::floor)+1. || sec->floorplane.isSlope())
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
sector->transdoor=false;
|
|
|
|
return;
|
|
|
|
}
|
2017-01-02 20:40:52 +00:00
|
|
|
if (!ln->sidedef[1-side]->GetTexture(side_t::top).isValid()) notextures++;
|
|
|
|
if (!ln->sidedef[1-side]->GetTexture(side_t::bottom).isValid()) nobtextures++;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sector->GetTexture(sector_t::ceiling)==skyflatnum)
|
|
|
|
{
|
|
|
|
sector->transdoor=false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-02 20:40:52 +00:00
|
|
|
if (selfref+nobtextures!=sector->Lines.Size())
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
sector->transdoor=false;
|
|
|
|
}
|
|
|
|
|
2017-01-02 20:40:52 +00:00
|
|
|
if (selfref+notextures!=sector->Lines.Size())
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
// This is a crude attempt to fix an incorrect transparent door effect I found in some
|
|
|
|
// WolfenDoom maps but considering the amount of code required to handle it I left it in.
|
|
|
|
// Do this only if the sector only contains one-sided walls or ones with no lower texture.
|
|
|
|
if (solidwall)
|
|
|
|
{
|
2017-01-02 20:40:52 +00:00
|
|
|
if (solidwall+nobtextures+selfref==sector->Lines.Size() && nextsec)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
sector->heightsec=nextsec;
|
|
|
|
sector->heightsec->MoreFlags=0;
|
|
|
|
}
|
|
|
|
sector->transdoor=false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void AddToVertex(const sector_t * sec, TArray<int> & list)
|
|
|
|
{
|
2017-01-07 19:02:25 +00:00
|
|
|
int secno = sec->Index();
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
for(unsigned i=0;i<list.Size();i++)
|
|
|
|
{
|
|
|
|
if (list[i]==secno) return;
|
|
|
|
}
|
|
|
|
list.Push(secno);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Attach sectors to vertices - used to generate vertex height lists
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void InitVertexData()
|
|
|
|
{
|
|
|
|
TArray<int> * vt_sectorlists;
|
|
|
|
|
|
|
|
int i,j,k;
|
|
|
|
|
|
|
|
vt_sectorlists = new TArray<int>[numvertexes];
|
|
|
|
|
|
|
|
|
2017-01-08 13:39:16 +00:00
|
|
|
for(auto &line : level.lines)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
for(j=0;j<2;j++)
|
|
|
|
{
|
2017-01-08 13:39:16 +00:00
|
|
|
vertex_t * v = j==0? line.v1 : line.v2;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
for(k=0;k<2;k++)
|
|
|
|
{
|
2017-01-08 13:39:16 +00:00
|
|
|
sector_t * sec = k==0? line.frontsector : line.backsector;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
if (sec)
|
|
|
|
{
|
|
|
|
extsector_t::xfloor &x = sec->e->XFloor;
|
|
|
|
|
|
|
|
AddToVertex(sec, vt_sectorlists[v-vertexes]);
|
|
|
|
if (sec->heightsec) AddToVertex(sec->heightsec, vt_sectorlists[v-vertexes]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0;i<numvertexes;i++)
|
|
|
|
{
|
|
|
|
int cnt = vt_sectorlists[i].Size();
|
|
|
|
|
|
|
|
vertexes[i].dirty = true;
|
|
|
|
vertexes[i].numheights=0;
|
|
|
|
if (cnt>1)
|
|
|
|
{
|
|
|
|
vertexes[i].numsectors= cnt;
|
|
|
|
vertexes[i].sectors=new sector_t*[cnt];
|
|
|
|
vertexes[i].heightlist = new float[cnt*2];
|
|
|
|
for(int j=0;j<cnt;j++)
|
|
|
|
{
|
2017-01-07 18:32:24 +00:00
|
|
|
vertexes[i].sectors[j] = &level.sectors[vt_sectorlists[i][j]];
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vertexes[i].numsectors=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete [] vt_sectorlists;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2016-04-03 09:40:14 +00:00
|
|
|
static void GetSideVertices(int sdnum, DVector2 *v1, DVector2 *v2)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
line_t *ln = sides[sdnum].linedef;
|
|
|
|
if (ln->sidedef[0] == &sides[sdnum])
|
|
|
|
{
|
2016-04-03 09:40:14 +00:00
|
|
|
*v1 = ln->v1->fPos();
|
|
|
|
*v2 = ln->v2->fPos();
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-04-03 09:40:14 +00:00
|
|
|
*v2 = ln->v1->fPos();
|
|
|
|
*v1 = ln->v2->fPos();
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-11 08:55:09 +00:00
|
|
|
static int segcmp(const void *a, const void *b)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
seg_t *A = *(seg_t**)a;
|
|
|
|
seg_t *B = *(seg_t**)b;
|
|
|
|
return xs_RoundToInt(FRACUNIT*(A->sidefrac - B->sidefrac));
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Group segs to sidedefs
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void PrepareSegs()
|
|
|
|
{
|
|
|
|
int *segcount = new int[numsides];
|
|
|
|
int realsegs = 0;
|
|
|
|
|
|
|
|
// Get floatng point coordinates of vertices
|
|
|
|
for(int i = 0; i < numvertexes; i++)
|
|
|
|
{
|
|
|
|
vertexes[i].dirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// count the segs
|
|
|
|
memset(segcount, 0, numsides * sizeof(int));
|
|
|
|
|
|
|
|
// set up the extra data in case the map was loaded with regular nodes that might pass as GL nodes.
|
|
|
|
if (glsegextras == NULL)
|
|
|
|
{
|
|
|
|
for(int i=0;i<numsegs;i++)
|
|
|
|
{
|
|
|
|
segs[i].PartnerSeg = NULL;
|
|
|
|
}
|
|
|
|
for (int i=0; i<numsubsectors; i++)
|
|
|
|
{
|
|
|
|
int seg = int(subsectors[i].firstline-segs);
|
|
|
|
for(DWORD j=0;j<subsectors[i].numlines;j++)
|
|
|
|
{
|
|
|
|
segs[j+seg].Subsector = &subsectors[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for(int i=0;i<numsegs;i++)
|
|
|
|
{
|
|
|
|
seg_t *seg = &segs[i];
|
|
|
|
|
|
|
|
// Account for ZDoom space optimizations that cannot be done for GL
|
|
|
|
unsigned int partner= glsegextras[i].PartnerSeg;
|
|
|
|
if (partner < unsigned(numsegs)) seg->PartnerSeg = &segs[partner];
|
|
|
|
else seg->PartnerSeg = NULL;
|
|
|
|
seg->Subsector = glsegextras[i].Subsector;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i=0;i<numsegs;i++)
|
|
|
|
{
|
|
|
|
seg_t *seg = &segs[i];
|
|
|
|
|
|
|
|
if (seg->sidedef == NULL) continue; // miniseg
|
|
|
|
int sidenum = int(seg->sidedef - sides);
|
|
|
|
|
|
|
|
realsegs++;
|
|
|
|
segcount[sidenum]++;
|
2016-04-03 09:40:14 +00:00
|
|
|
DVector2 sidestart, sideend, segend = seg->v2->fPos();
|
2013-06-23 07:49:34 +00:00
|
|
|
GetSideVertices(sidenum, &sidestart, &sideend);
|
|
|
|
|
|
|
|
sideend -=sidestart;
|
|
|
|
segend -= sidestart;
|
|
|
|
|
|
|
|
seg->sidefrac = float(segend.Length() / sideend.Length());
|
|
|
|
}
|
|
|
|
|
|
|
|
// allocate memory
|
|
|
|
sides[0].segs = new seg_t*[realsegs];
|
|
|
|
sides[0].numsegs = 0;
|
|
|
|
|
|
|
|
for(int i = 1; i < numsides; i++)
|
|
|
|
{
|
|
|
|
sides[i].segs = sides[i-1].segs + segcount[i-1];
|
|
|
|
sides[i].numsegs = 0;
|
|
|
|
}
|
|
|
|
delete [] segcount;
|
|
|
|
|
|
|
|
// assign the segs
|
|
|
|
for(int i=0;i<numsegs;i++)
|
|
|
|
{
|
|
|
|
seg_t *seg = &segs[i];
|
|
|
|
if (seg->sidedef != NULL) seg->sidedef->segs[seg->sidedef->numsegs++] = seg;
|
|
|
|
}
|
|
|
|
|
|
|
|
// sort the segs
|
|
|
|
for(int i = 0; i < numsides; i++)
|
|
|
|
{
|
|
|
|
if (sides[i].numsegs > 1) qsort(sides[i].segs, sides[i].numsegs, sizeof(seg_t*), segcmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Initialize the level data for the GL renderer
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
extern int restart;
|
|
|
|
|
|
|
|
void gl_PreprocessLevel()
|
|
|
|
{
|
|
|
|
PrepareSegs();
|
|
|
|
PrepareSectorData();
|
|
|
|
InitVertexData();
|
2014-07-27 15:57:53 +00:00
|
|
|
int *checkmap = new int[numvertexes];
|
|
|
|
memset(checkmap, -1, sizeof(int)*numvertexes);
|
2017-01-07 18:32:24 +00:00
|
|
|
for(auto &sec : level.sectors)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2017-01-07 18:32:24 +00:00
|
|
|
int i = sec.sectornum;
|
|
|
|
PrepareTransparentDoors(&sec);
|
2014-07-27 15:57:53 +00:00
|
|
|
|
|
|
|
// This ignores vertices only used for seg splitting because those aren't needed here
|
2017-01-07 18:32:24 +00:00
|
|
|
for(auto l : sec.Lines)
|
2014-07-27 15:57:53 +00:00
|
|
|
{
|
|
|
|
if (l->sidedef[0]->Flags & WALLF_POLYOBJ) continue; // don't bother with polyobjects
|
|
|
|
|
|
|
|
int vtnum1 = int(l->v1 - vertexes);
|
|
|
|
int vtnum2 = int(l->v2 - vertexes);
|
|
|
|
|
2014-07-28 20:23:17 +00:00
|
|
|
if (checkmap[vtnum1] < i)
|
2014-07-27 15:57:53 +00:00
|
|
|
{
|
2014-07-28 20:23:17 +00:00
|
|
|
checkmap[vtnum1] = i;
|
2017-01-07 18:32:24 +00:00
|
|
|
sec.e->vertices.Push(&vertexes[vtnum1]);
|
2014-07-27 15:57:53 +00:00
|
|
|
vertexes[vtnum1].dirty = true;
|
|
|
|
}
|
|
|
|
|
2014-07-28 20:23:17 +00:00
|
|
|
if (checkmap[vtnum2] < i)
|
2014-07-27 15:57:53 +00:00
|
|
|
{
|
2014-07-28 20:23:17 +00:00
|
|
|
checkmap[vtnum2] = i;
|
2017-01-07 18:32:24 +00:00
|
|
|
sec.e->vertices.Push(&vertexes[vtnum2]);
|
2014-07-27 15:57:53 +00:00
|
|
|
vertexes[vtnum2].dirty = true;
|
|
|
|
}
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2014-07-27 15:57:53 +00:00
|
|
|
delete[] checkmap;
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
gl_InitPortals();
|
|
|
|
|
|
|
|
if (GLRenderer != NULL)
|
|
|
|
{
|
|
|
|
GLRenderer->SetupLevel();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
gl_CreateSections();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
InitGLRMapinfoData();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Cleans up all the GL data for the last level
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void gl_CleanLevelData()
|
|
|
|
{
|
|
|
|
// Dynamic lights must be destroyed before the sector information here is deleted.
|
|
|
|
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
|
|
|
AActor * mo=it.Next();
|
|
|
|
while (mo)
|
|
|
|
{
|
|
|
|
AActor * next = it.Next();
|
|
|
|
mo->Destroy();
|
|
|
|
mo=next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vertexes != NULL)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < numvertexes; i++) if (vertexes[i].numsectors > 0)
|
|
|
|
{
|
|
|
|
if (vertexes[i].sectors != NULL)
|
|
|
|
{
|
|
|
|
delete [] vertexes[i].sectors;
|
|
|
|
vertexes[i].sectors = NULL;
|
|
|
|
}
|
|
|
|
if (vertexes[i].heightlist != NULL)
|
|
|
|
{
|
|
|
|
delete [] vertexes[i].heightlist;
|
|
|
|
vertexes[i].heightlist = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sides && sides[0].segs)
|
|
|
|
{
|
|
|
|
delete [] sides[0].segs;
|
|
|
|
sides[0].segs = NULL;
|
|
|
|
}
|
2017-01-07 18:32:24 +00:00
|
|
|
if (level.sectors.Size() > 0 && level.sectors[0].subsectors)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2017-01-07 18:32:24 +00:00
|
|
|
delete [] level.sectors[0].subsectors;
|
|
|
|
level.sectors[0].subsectors = nullptr;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
for (int i=0;i<numsubsectors;i++)
|
|
|
|
{
|
|
|
|
for(int j=0;j<2;j++)
|
|
|
|
{
|
|
|
|
if (subsectors[i].portalcoverage[j].subsectors != NULL)
|
|
|
|
{
|
|
|
|
delete [] subsectors[i].portalcoverage[j].subsectors;
|
|
|
|
subsectors[i].portalcoverage[j].subsectors = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(unsigned i=0;i<portals.Size(); i++)
|
|
|
|
{
|
|
|
|
delete portals[i];
|
|
|
|
}
|
|
|
|
portals.Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD(listmapsections)
|
|
|
|
{
|
|
|
|
for(int i=0;i<100;i++)
|
|
|
|
{
|
|
|
|
for (int j=0;j<numsubsectors;j++)
|
|
|
|
{
|
|
|
|
if (subsectors[j].mapsection == i)
|
|
|
|
{
|
2017-01-08 13:39:16 +00:00
|
|
|
Printf("Mapsection %d, sector %d, line %d\n", i, subsectors[j].render_sector->Index(), subsectors[j].firstline->linedef->Index());
|
2013-06-23 07:49:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-28 06:33:11 +00:00
|
|
|
}
|