mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-25 05:31:00 +00:00
845 lines
21 KiB
C++
845 lines
21 KiB
C++
/*
|
|
** gl_sections.cpp
|
|
** Splits sectors into continuous separate parts
|
|
**
|
|
**---------------------------------------------------------------------------
|
|
** Copyright 2008 Christoph Oelckers
|
|
** All rights reserved.
|
|
**
|
|
** Redistribution and use in source and binary forms, with or without
|
|
** modification, are permitted provided that the following conditions
|
|
** are met:
|
|
**
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
** notice, this list of conditions and the following disclaimer.
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
** documentation and/or other materials provided with the distribution.
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
** derived from this software without specific prior written permission.
|
|
** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be
|
|
** covered by the terms of the GNU Lesser General Public License as published
|
|
** by the Free Software Foundation; either version 2.1 of the License, or (at
|
|
** your option) any later version.
|
|
** 5. Full disclosure of the entire project's source code, except for third
|
|
** party libraries is mandatory. (NOTE: This clause is non-negotiable!)
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
**---------------------------------------------------------------------------
|
|
**
|
|
*/
|
|
|
|
#include "gl/system/gl_system.h"
|
|
#include <GL/GLU.h>
|
|
#include "i_system.h"
|
|
#include "p_local.h"
|
|
#include "c_dispatch.h"
|
|
#include "gl/data/gl_sections.h"
|
|
|
|
typedef void (CALLBACK *tessFunc)();
|
|
|
|
TArray<FGLSectionLine> SectionLines;
|
|
TArray<FGLSectionLoop> SectionLoops;
|
|
TArray<FGLSection> Sections;
|
|
TArray<int> SectionForSubsector;
|
|
|
|
CVAR (Bool, dumpsections, false, 0)
|
|
|
|
#define ISDONE(no, p) (p[(no)>>3] & (1 << ((no)&7)))
|
|
#define SETDONE(no, p) p[(no)>>3] |= (1 << ((no)&7))
|
|
|
|
inline vertex_t *V1(side_t *s)
|
|
{
|
|
line_t *ln = s->linedef;
|
|
return s == ln->sidedef[0]? ln->v1: ln->v2;
|
|
}
|
|
|
|
inline vertex_t *V2(side_t *s)
|
|
{
|
|
line_t *ln = s->linedef;
|
|
return s == ln->sidedef[0]? ln->v2: ln->v1;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
class FSectionCreator
|
|
{
|
|
static FSectionCreator *creator;
|
|
|
|
uint8_t *processed_segs;
|
|
uint8_t *processed_subsectors;
|
|
int *section_for_segs;
|
|
|
|
vertex_t *v1_l1, *v2_l1;
|
|
|
|
FGLSectionLoop *loop;
|
|
FGLSection *section; // current working section
|
|
|
|
public:
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
FSectionCreator()
|
|
{
|
|
processed_segs = new uint8_t[(numsegs+7)/8];
|
|
processed_subsectors = new uint8_t[(numsubsectors+7)/8];
|
|
|
|
memset(processed_segs, 0, (numsegs+7)/8);
|
|
memset(processed_subsectors, 0, (numsubsectors+7)/8);
|
|
|
|
section_for_segs = new int[numsegs];
|
|
memset(section_for_segs, -1, numsegs * sizeof(int));
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
~FSectionCreator()
|
|
{
|
|
delete [] processed_segs;
|
|
delete [] processed_subsectors;
|
|
delete [] section_for_segs;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
void NewLoop()
|
|
{
|
|
section->numloops++;
|
|
loop = &SectionLoops[SectionLoops.Reserve(1)];
|
|
loop->startline = SectionLines.Size();
|
|
loop->numlines = 0 ;
|
|
}
|
|
|
|
void NewSection(sector_t *sec)
|
|
{
|
|
section = &Sections[Sections.Reserve(1)];
|
|
section->sector = sec;
|
|
section->subsectors.Clear();
|
|
section->numloops = 0;
|
|
section->startloop = SectionLoops.Size();
|
|
section->validcount = -1;
|
|
NewLoop();
|
|
}
|
|
|
|
void FinalizeSection()
|
|
{
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
bool AddSeg(seg_t *seg)
|
|
{
|
|
FGLSectionLine &line = SectionLines[SectionLines.Reserve(1)];
|
|
|
|
|
|
bool firstline = loop->numlines == 0;
|
|
|
|
if (ISDONE(seg-segs, processed_segs))
|
|
{
|
|
// should never happen!
|
|
DPrintf("Tried to add seg %d to Sections twice. Cannot create Sections.\n", seg-segs);
|
|
return false;
|
|
}
|
|
|
|
SETDONE(seg-segs, processed_segs);
|
|
section_for_segs[seg-segs] = Sections.Size()-1;
|
|
|
|
line.start = seg->v1;
|
|
line.end = seg->v2;
|
|
line.sidedef = seg->sidedef;
|
|
line.linedef = seg->linedef;
|
|
line.refseg = seg;
|
|
line.polysub = NULL;
|
|
line.otherside = -1;
|
|
|
|
if (loop->numlines == 0)
|
|
{
|
|
v1_l1 = seg->v1;
|
|
v2_l1 = seg->v2;
|
|
}
|
|
loop->numlines++;
|
|
return true;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// Utility stuff
|
|
//
|
|
//==========================================================================
|
|
|
|
sector_t *FrontRenderSector(seg_t *seg)
|
|
{
|
|
return seg->Subsector->render_sector;
|
|
}
|
|
|
|
sector_t *BackRenderSector(seg_t *seg)
|
|
{
|
|
if (seg->PartnerSeg == NULL) return NULL;
|
|
return seg->PartnerSeg->Subsector->render_sector;
|
|
}
|
|
|
|
bool IntraSectorSeg(seg_t *seg)
|
|
{
|
|
return FrontRenderSector(seg) == BackRenderSector(seg);
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// returns the seg whose partner seg determines where this
|
|
// section continues
|
|
//
|
|
//==========================================================================
|
|
bool AddSubSector(subsector_t *subsec, vertex_t *startpt, seg_t **pNextSeg)
|
|
{
|
|
unsigned i = 0;
|
|
if (startpt != NULL)
|
|
{
|
|
// find the seg in this subsector that starts at the given vertex
|
|
for(i = 0; i < subsec->numlines; i++)
|
|
{
|
|
if (subsec->firstline[i].v1 == startpt) break;
|
|
}
|
|
if (i == subsec->numlines)
|
|
{
|
|
DPrintf("Vertex not found in subsector %d. Cannot create Sections.\n", subsec-subsectors);
|
|
return false; // Nodes are bad
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Find the first unprocessed non-miniseg
|
|
for(i = 0; i < subsec->numlines; i++)
|
|
{
|
|
seg_t *seg = subsec->firstline + i;
|
|
|
|
if (seg->sidedef == NULL) continue;
|
|
if (IntraSectorSeg(seg)) continue;
|
|
if (ISDONE(seg-segs, processed_segs)) continue;
|
|
break;
|
|
}
|
|
if (i == subsec->numlines)
|
|
{
|
|
DPrintf("Unable to find a start seg. Cannot create Sections.\n");
|
|
return false; // Nodes are bad
|
|
}
|
|
|
|
startpt = subsec->firstline[i].v1;
|
|
}
|
|
|
|
seg_t *thisseg = subsec->firstline + i;
|
|
if (IntraSectorSeg(thisseg))
|
|
{
|
|
SETDONE(thisseg-segs, processed_segs);
|
|
// continue with the loop in the adjoining subsector
|
|
*pNextSeg = thisseg;
|
|
return true;
|
|
}
|
|
|
|
while(1)
|
|
{
|
|
if (loop->numlines > 0 && thisseg->v1 == v1_l1 && thisseg->v2 == v2_l1)
|
|
{
|
|
// This loop is complete
|
|
*pNextSeg = NULL;
|
|
return true;
|
|
}
|
|
|
|
if (!AddSeg(thisseg)) return NULL;
|
|
|
|
i = (i+1) % subsec->numlines;
|
|
seg_t *nextseg = subsec->firstline + i;
|
|
|
|
if (thisseg->v2 != nextseg->v1)
|
|
{
|
|
DPrintf("Segs in subsector %d are not continuous. Cannot create Sections.\n", subsec-subsectors);
|
|
return false; // Nodes are bad
|
|
}
|
|
|
|
if (IntraSectorSeg(nextseg))
|
|
{
|
|
SETDONE(nextseg-segs, processed_segs);
|
|
// continue with the loop in the adjoining subsector
|
|
*pNextSeg = nextseg;
|
|
return true;
|
|
}
|
|
thisseg = nextseg;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
//
|
|
//
|
|
//=============================================================================
|
|
|
|
bool FindNextSeg(seg_t **pSeg)
|
|
{
|
|
// find an unprocessed non-miniseg or a miniseg with an unprocessed
|
|
// partner subsector that belongs to the same rendersector
|
|
for (unsigned i = 0; i < section->subsectors.Size(); i++)
|
|
{
|
|
for(unsigned j = 0; j < section->subsectors[i]->numlines; j++)
|
|
{
|
|
seg_t *seg = section->subsectors[i]->firstline + j;
|
|
bool intra = IntraSectorSeg(seg);
|
|
|
|
if (!intra && !ISDONE(seg-segs, processed_segs))
|
|
{
|
|
*pSeg = seg;
|
|
return true;
|
|
}
|
|
else if (intra &&
|
|
!ISDONE(seg->PartnerSeg->Subsector-subsectors, processed_subsectors))
|
|
{
|
|
*pSeg = seg->PartnerSeg;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
*pSeg = NULL;
|
|
return true;
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// all segs and subsectors must be grouped into Sections
|
|
//
|
|
//=============================================================================
|
|
bool CheckSections()
|
|
{
|
|
bool res = true;
|
|
for (int i = 0; i < numsegs; i++)
|
|
{
|
|
if (segs[i].sidedef != NULL && !ISDONE(i, processed_segs) && !IntraSectorSeg(&segs[i]))
|
|
{
|
|
Printf("Seg %d (Linedef %d) not processed during section creation\n", i, segs[i].linedef-lines);
|
|
res = false;
|
|
}
|
|
}
|
|
for (int i = 0; i < numsubsectors; i++)
|
|
{
|
|
if (!ISDONE(i, processed_subsectors))
|
|
{
|
|
Printf("Subsector %d (Sector %d) not processed during section creation\n", i, subsectors[i].sector-sectors);
|
|
res = false;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
//
|
|
//
|
|
//=============================================================================
|
|
void DeleteLine(int i)
|
|
{
|
|
SectionLines.Delete(i);
|
|
for(int i = SectionLoops.Size() - 1; i >= 0; i--)
|
|
{
|
|
FGLSectionLoop *loop = &SectionLoops[i];
|
|
if (loop->startline > i) loop->startline--;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
//
|
|
//
|
|
//=============================================================================
|
|
void MergeLines(FGLSectionLoop *loop)
|
|
{
|
|
int i;
|
|
int deleted = 0;
|
|
FGLSectionLine *ln1;
|
|
FGLSectionLine *ln2;
|
|
// Merge identical lines in the list
|
|
for(i = loop->numlines - 1; i > 0; i--)
|
|
{
|
|
ln1 = loop->GetLine(i);
|
|
ln2 = loop->GetLine(i-1);
|
|
|
|
if (ln1->sidedef == ln2->sidedef && ln1->otherside == ln2->otherside)
|
|
{
|
|
// identical references. These 2 lines can be merged.
|
|
ln2->end = ln1->end;
|
|
SectionLines.Delete(loop->startline + i);
|
|
loop->numlines--;
|
|
deleted++;
|
|
}
|
|
}
|
|
|
|
// If we started in the middle of a sidedef the first and last lines
|
|
// may reference the same sidedef. check that, too.
|
|
|
|
int loopstart = 0;
|
|
|
|
ln1 = loop->GetLine(0);
|
|
for(i = loop->numlines - 1; i > 0; i--)
|
|
{
|
|
ln2 = loop->GetLine(i);
|
|
if (ln1->sidedef != ln2->sidedef || ln1->otherside != ln2->otherside)
|
|
break;
|
|
}
|
|
if (i < loop->numlines-1)
|
|
{
|
|
i++;
|
|
ln2 = loop->GetLine(i);
|
|
ln1->start = ln2->start;
|
|
SectionLines.Delete(loop->startline + i, loop->numlines - i);
|
|
deleted += loop->numlines - i;
|
|
loop->numlines = i;
|
|
}
|
|
|
|
// Adjust all following loops
|
|
for(unsigned ii = unsigned(loop - &SectionLoops[0]) + 1; ii < SectionLoops.Size(); ii++)
|
|
{
|
|
SectionLoops[ii].startline -= deleted;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
//
|
|
//
|
|
//=============================================================================
|
|
void SetReferences()
|
|
{
|
|
for(unsigned i = 0; i < SectionLines.Size(); i++)
|
|
{
|
|
FGLSectionLine *ln = &SectionLines[i];
|
|
seg_t *seg = ln->refseg;
|
|
|
|
if (seg != NULL)
|
|
{
|
|
seg_t *partner = seg->PartnerSeg;
|
|
|
|
if (seg->PartnerSeg == NULL)
|
|
{
|
|
ln->otherside = -1;
|
|
}
|
|
else
|
|
{
|
|
ln->otherside = section_for_segs[partner-segs];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ln->otherside = -1;
|
|
}
|
|
}
|
|
|
|
for(unsigned i = 0; i < SectionLoops.Size(); i++)
|
|
{
|
|
MergeLines(&SectionLoops[i]);
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// cbTessBegin
|
|
//
|
|
// called when the tesselation of a new loop starts
|
|
//
|
|
//=============================================================================
|
|
|
|
static void CALLBACK cbTessBegin(GLenum type, void *section)
|
|
{
|
|
FGLSection *sect = (FGLSection*)section;
|
|
sect->primitives.Push(type);
|
|
sect->primitives.Push(sect->vertices.Size());
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// cbTessError
|
|
//
|
|
// called when the tesselation failed
|
|
//
|
|
//=============================================================================
|
|
|
|
static void CALLBACK cbTessError(GLenum error, void *section)
|
|
{
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// cbTessCombine
|
|
//
|
|
// called when the two or more vertexes are on the same coordinate
|
|
//
|
|
//=============================================================================
|
|
|
|
static void CALLBACK cbTessCombine( GLdouble coords[3], void *vert[4], GLfloat w[4], void **dataOut )
|
|
{
|
|
*dataOut = vert[0];
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// cbTessVertex
|
|
//
|
|
// called when a vertex is found
|
|
//
|
|
//=============================================================================
|
|
|
|
static void CALLBACK cbTessVertex( void *vert, void *section )
|
|
{
|
|
FGLSection *sect = (FGLSection*)section;
|
|
sect->vertices.Push(int(intptr_t(vert)));
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// cbTessEnd
|
|
//
|
|
// called when the tesselation of a the current loop ends
|
|
//
|
|
//=============================================================================
|
|
|
|
static void CALLBACK cbTessEnd(void *section)
|
|
{
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
//
|
|
//
|
|
//=============================================================================
|
|
void tesselateSections()
|
|
{
|
|
// init tesselator
|
|
GLUtesselator *tess = gluNewTess();
|
|
if (!tess)
|
|
{
|
|
return;
|
|
}
|
|
// set callbacks
|
|
gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (tessFunc)cbTessBegin);
|
|
gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (tessFunc)cbTessVertex);
|
|
gluTessCallback(tess, GLU_TESS_ERROR_DATA, (tessFunc)cbTessError);
|
|
gluTessCallback(tess, GLU_TESS_COMBINE, (tessFunc)cbTessCombine);
|
|
gluTessCallback(tess, GLU_TESS_END_DATA, (tessFunc)cbTessEnd);
|
|
|
|
for(unsigned int i=0;i<Sections.Size(); i++)
|
|
{
|
|
FGLSection *sect = &Sections[i];
|
|
|
|
gluTessBeginPolygon(tess, sect);
|
|
|
|
for(int j=0; j< sect->numloops; j++)
|
|
{
|
|
gluTessBeginContour(tess);
|
|
FGLSectionLoop *loop = sect->GetLoop(j);
|
|
for(int k=0; k<loop->numlines; k++)
|
|
{
|
|
FGLSectionLine *line = loop->GetLine(k);
|
|
vertex_t *vert = line->start;
|
|
GLdouble v[3] = {
|
|
-(double)vert->x/(double)FRACUNIT, // negate to get proper winding
|
|
0.0,
|
|
(double)vert->y/(double)FRACUNIT
|
|
};
|
|
gluTessVertex(tess, v, (void*)(vert - vertexes));
|
|
}
|
|
gluTessEndContour(tess);
|
|
}
|
|
gluTessEndPolygon(tess);
|
|
sect->vertices.Push(-1337);
|
|
sect->vertices.ShrinkToFit();
|
|
}
|
|
gluDeleteTess(tess);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// First mark all subsectors that have no outside boundaries as processed
|
|
// No line in such a subsector will ever be part of a section's border
|
|
//
|
|
//=============================================================================
|
|
|
|
void MarkInternalSubsectors()
|
|
{
|
|
for(int i=0; i < numsubsectors; i++)
|
|
{
|
|
subsector_t *sub = &subsectors[i];
|
|
int j;
|
|
|
|
for(j=0; j < sub->numlines; j++)
|
|
{
|
|
seg_t *seg = sub->firstline + j;
|
|
if (!IntraSectorSeg(seg)) break;
|
|
}
|
|
if (j==sub->numlines)
|
|
{
|
|
// All lines are intra-sector so mark this as processed
|
|
SETDONE(i, processed_subsectors);
|
|
for(j=0; j < sub->numlines; j++)
|
|
{
|
|
seg_t *seg = sub->firstline + j;
|
|
SETDONE((sub->firstline-segs)+j, processed_segs);
|
|
if (seg->PartnerSeg != NULL)
|
|
{
|
|
SETDONE(int(seg->PartnerSeg - segs), processed_segs);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
//
|
|
//
|
|
//=============================================================================
|
|
bool CreateSections()
|
|
{
|
|
int pick = 0;
|
|
|
|
MarkInternalSubsectors();
|
|
while (pick < numsubsectors)
|
|
{
|
|
if (ISDONE(pick, processed_subsectors))
|
|
{
|
|
pick++;
|
|
continue;
|
|
}
|
|
|
|
|
|
subsector_t *subsector = &subsectors[pick];
|
|
|
|
seg_t *workseg = NULL;
|
|
vertex_t *startpt = NULL;
|
|
|
|
NewSection(subsector->render_sector);
|
|
while (1)
|
|
{
|
|
if (!ISDONE(subsector-subsectors, processed_subsectors))
|
|
{
|
|
SETDONE(subsector-subsectors, processed_subsectors);
|
|
section->subsectors.Push(subsector);
|
|
SectionForSubsector[subsector - subsectors] = int(section - &Sections[0]);
|
|
}
|
|
|
|
bool result = AddSubSector(subsector, startpt, &workseg);
|
|
|
|
if (!result)
|
|
{
|
|
return false; // couldn't create Sections
|
|
}
|
|
else if (workseg != NULL)
|
|
{
|
|
// crossing into another subsector
|
|
seg_t *partner = workseg->PartnerSeg;
|
|
if (workseg->v2 != partner->v1)
|
|
{
|
|
DPrintf("Inconsistent subsector references in seg %d. Cannot create Sections.\n", workseg-segs);
|
|
return false;
|
|
}
|
|
subsector = partner->Subsector;
|
|
startpt = workseg->v1;
|
|
}
|
|
else
|
|
{
|
|
// loop complete. Check adjoining subsectors for other loops to
|
|
// be added to this section
|
|
if (!FindNextSeg(&workseg))
|
|
{
|
|
return false;
|
|
}
|
|
else if (workseg == NULL)
|
|
{
|
|
// No more subsectors found. This section is complete!
|
|
FinalizeSection();
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
subsector = workseg->Subsector;
|
|
// If this is a regular seg, start there, otherwise start
|
|
// at the subsector's first seg
|
|
startpt = workseg->sidedef == NULL? NULL : workseg->v1;
|
|
|
|
NewLoop();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!CheckSections()) return false;
|
|
SetReferences();
|
|
|
|
Sections.ShrinkToFit();
|
|
SectionLoops.ShrinkToFit();
|
|
SectionLines.ShrinkToFit();
|
|
|
|
tesselateSections();
|
|
|
|
return true;
|
|
}
|
|
};
|
|
|
|
FSectionCreator *FSectionCreator::creator;
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
//
|
|
//
|
|
//=============================================================================
|
|
|
|
void DumpSection(int no, FGLSection *sect)
|
|
{
|
|
Printf(PRINT_LOG, "Section %d, sector %d\n{\n", no, sect->sector->sectornum);
|
|
|
|
for(int i = 0; i < sect->numloops; i++)
|
|
{
|
|
Printf(PRINT_LOG, "\tLoop %d\n\t{\n", i);
|
|
|
|
FGLSectionLoop *loop = sect->GetLoop(i);
|
|
|
|
for(int i = 0; i < loop->numlines; i++)
|
|
{
|
|
FGLSectionLine *ln = loop->GetLine(i);
|
|
if (ln->sidedef != NULL)
|
|
{
|
|
vertex_t *v1 = V1(ln->sidedef);
|
|
vertex_t *v2 = V2(ln->sidedef);
|
|
double dx = FIXED2DBL(v2->x-v1->x);
|
|
double dy = FIXED2DBL(v2->y-v1->y);
|
|
double dx1 = FIXED2DBL(ln->start->x-v1->x);
|
|
double dy1 = FIXED2DBL(ln->start->y-v1->y);
|
|
double dx2 = FIXED2DBL(ln->end->x-v1->x);
|
|
double dy2 = FIXED2DBL(ln->end->y-v1->y);
|
|
double d = sqrt(dx*dx+dy*dy);
|
|
double d1 = sqrt(dx1*dx1+dy1*dy1);
|
|
double d2 = sqrt(dx2*dx2+dy2*dy2);
|
|
|
|
Printf(PRINT_LOG, "\t\tLinedef %d, %s: Start (%1.2f, %1.2f), End (%1.2f, %1.2f)",
|
|
ln->linedef - lines, ln->sidedef == ln->linedef->sidedef[0]? "front":"back",
|
|
ln->start->x/65536.f, ln->start->y/65536.f,
|
|
ln->end->x/65536.f, ln->end->y/65536.f);
|
|
|
|
if (ln->otherside != -1)
|
|
{
|
|
Printf (PRINT_LOG, ", other side = %d", ln->otherside);
|
|
}
|
|
if (d1 > 0.005 || d2 < 0.995)
|
|
{
|
|
Printf(PRINT_LOG, ", Range = %1.3f, %1.3f", d1/d, d2/d);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Printf(PRINT_LOG, "\t\tMiniseg: Start (%1.3f, %1.3f), End (%1.3f, %1.3f)\n",
|
|
ln->start->x/65536.f, ln->start->y/65536.f, ln->end->x/65536.f, ln->end->y/65536.f);
|
|
|
|
if (ln->otherside != -1)
|
|
{
|
|
Printf (PRINT_LOG, ", other side = %d", ln->otherside);
|
|
}
|
|
}
|
|
Printf(PRINT_LOG, "\n");
|
|
}
|
|
Printf(PRINT_LOG, "\t}\n");
|
|
}
|
|
int prim = 1;
|
|
for(unsigned i = 0; i < sect->vertices.Size(); i++)
|
|
{
|
|
int v = sect->vertices[i];
|
|
if (v < 0)
|
|
{
|
|
if (i > 0)
|
|
{
|
|
Printf(PRINT_LOG, "\t}\n");
|
|
}
|
|
switch (v)
|
|
{
|
|
case -GL_TRIANGLE_FAN:
|
|
Printf(PRINT_LOG, "\t%d: Triangle fan\n\t{\n", prim);
|
|
break;
|
|
|
|
case -GL_TRIANGLE_STRIP:
|
|
Printf(PRINT_LOG, "\t%d: Triangle strip\n\t{\n", prim);
|
|
break;
|
|
|
|
case -GL_TRIANGLES:
|
|
Printf(PRINT_LOG, "\t%d: Triangles\n\t{\n", prim);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
prim++;
|
|
}
|
|
else
|
|
{
|
|
Printf(PRINT_LOG, "\t\tVertex %d: (%1.2f, %1.2f)\n",
|
|
v, vertexes[v].x/65536.f, vertexes[v].y/65536.f);
|
|
}
|
|
}
|
|
Printf(PRINT_LOG, "}\n\n");
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
//
|
|
//
|
|
//=============================================================================
|
|
|
|
void DumpSections()
|
|
{
|
|
for(unsigned i = 0; i < Sections.Size(); i++)
|
|
{
|
|
DumpSection(i, &Sections[i]);
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
//
|
|
//
|
|
//=============================================================================
|
|
|
|
void gl_CreateSections()
|
|
{
|
|
SectionLines.Clear();
|
|
SectionLoops.Clear();
|
|
Sections.Clear();
|
|
SectionForSubsector.Resize(numsubsectors);
|
|
memset(&SectionForSubsector[0], -1, numsubsectors * sizeof(SectionForSubsector[0]));
|
|
FSectionCreator creat;
|
|
creat.CreateSections();
|
|
if (dumpsections) DumpSections();
|
|
}
|
|
|