示例#1
0
	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;
	}
	//=============================================================================
	//
	// 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;
	}
	//=============================================================================
	//
	//
	//
	//=============================================================================
	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;
	}
	//==========================================================================
	//
	// 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;
		}
	}