void FNodeBuilder::Extract (FLevelLocals &level)
{
	int i;

	auto &outVerts = level.vertexes; 
	int vertCount = Vertices.Size ();
	outVerts.Alloc(vertCount);

	for (i = 0; i < vertCount; ++i)
	{
		outVerts[i].set(Vertices[i].x, Vertices[i].y);
	}

	auto &outSubs = level.subsectors;
	auto subCount = Subsectors.Size();
	outSubs.Alloc(subCount);
	memset(&outSubs[0], 0, subCount * sizeof(subsector_t));

	auto &outNodes = level.nodes;
	auto nodeCount = Nodes.Size ();
	outNodes.Alloc(nodeCount);

	memcpy (&outNodes[0], &Nodes[0], nodeCount*sizeof(node_t));
	for (unsigned i = 0; i < nodeCount; ++i)
	{
		D(Printf(PRINT_LOG, "Node %d:  Splitter[%08x,%08x] [%08x,%08x]\n", i,
			outNodes[i].x, outNodes[i].y, outNodes[i].dx, outNodes[i].dy));
		// Go backwards because on 64-bit systems, both of the intchildren are
		// inside the first in-game child.
		for (int j = 1; j >= 0; --j)
		{
			if (outNodes[i].intchildren[j] & 0x80000000)
			{
				D(Printf(PRINT_LOG, "  subsector %d\n", outNodes[i].intchildren[j] & 0x7FFFFFFF));
				outNodes[i].children[j] = (uint8_t *)(&outSubs[(outNodes[i].intchildren[j] & 0x7fffffff)]) + 1;
			}
			else
			{
				D(Printf(PRINT_LOG, "  node %d\n", outNodes[i].intchildren[j]));
				outNodes[i].children[j] = &outNodes[outNodes[i].intchildren[j]];
			}
		}
		for (int j = 0; j < 2; ++j)
		{
			for (int k = 0; k < 4; ++k)
			{
				outNodes[i].bbox[j][k] = FIXED2FLOAT(outNodes[i].nb_bbox[j][k]);
			}
		}
	}

	auto &outSegs = level.segs;
	if (GLNodes)
	{
		TArray<glseg_t> segs (Segs.Size()*5/4);

		for (unsigned i = 0; i < subCount; ++i)
		{
			uint32_t numsegs = CloseSubsector (segs, i, &outVerts[0]);
			outSubs[i].numlines = numsegs;
			outSubs[i].firstline = (seg_t *)(size_t)(segs.Size() - numsegs);
		}

		auto segCount = segs.Size ();
		outSegs.Alloc(segCount);

		for (unsigned i = 0; i < segCount; ++i)
		{
			outSegs[i] = *(seg_t *)&segs[i];

			if (segs[i].Partner != DWORD_MAX)
			{
				const uint32_t storedseg = Segs[segs[i].Partner].storedseg;
				outSegs[i].PartnerSeg = DWORD_MAX == storedseg ? nullptr : &outSegs[storedseg];
			}
			else
			{
				outSegs[i].PartnerSeg = nullptr;
			}
		}
	}
	else
	{
		memcpy (&outSubs[0], &Subsectors[0], subCount*sizeof(subsector_t));
		auto segCount = Segs.Size ();
		outSegs.Alloc(segCount);
		for (unsigned i = 0; i < segCount; ++i)
		{
			const FPrivSeg *org = &Segs[SegList[i].SegNum];
			seg_t *out = &outSegs[i];

			D(Printf(PRINT_LOG, "Seg %d: v1(%d) -> v2(%d)\n", i, org->v1, org->v2));

			out->v1 = &outVerts[org->v1];
			out->v2 = &outVerts[org->v2];
			out->backsector = org->backsector;
			out->frontsector = org->frontsector;
			out->linedef = Level.Lines + org->linedef;
			out->sidedef = Level.Sides + org->sidedef;
			out->PartnerSeg = nullptr;
		}
	}
	for (unsigned i = 0; i < subCount; ++i)
	{
		outSubs[i].firstline = &outSegs[(size_t)outSubs[i].firstline];
	}

	D(Printf("%i segs, %i nodes, %i subsectors\n", segCount, nodeCount, subCount));

	for (i = 0; i < Level.NumLines; ++i)
	{
		Level.Lines[i].v1 = &outVerts[(size_t)Level.Lines[i].v1];
		Level.Lines[i].v2 = &outVerts[(size_t)Level.Lines[i].v2];
	}
}
void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount,
	seg_t *&outSegs, int &segCount,
	subsector_t *&outSubs, int &subCount,
	vertex_t *&outVerts, int &vertCount)
{
	int i;

	vertCount = Vertices.Size ();
	outVerts = new vertex_t[vertCount];

	for (i = 0; i < vertCount; ++i)
	{
		outVerts[i].x = Vertices[i].x;
		outVerts[i].y = Vertices[i].y;
	}

	subCount = Subsectors.Size();
	outSubs = new subsector_t[subCount];

	nodeCount = Nodes.Size ();
	outNodes = new node_t[nodeCount];

	memcpy (outNodes, &Nodes[0], nodeCount*sizeof(node_t));
	for (i = 0; i < nodeCount; ++i)
	{
		for (int j = 0; j < 2; ++j)
		{
			if (outNodes[i].intchildren[j] & 0x80000000)
			{
				outNodes[i].children[j] = (BYTE *)(outSubs + (outNodes[i].intchildren[j] & 0x7fffffff)) + 1;
			}
			else
			{
				outNodes[i].children[j] = outNodes + outNodes[i].intchildren[j];
			}
		}
	}

	if (GLNodes)
	{
		TArray<seg_t> segs (Segs.Size()*5/4);

		for (i = 0; i < subCount; ++i)
		{
			DWORD numsegs = CloseSubsector (segs, i, outVerts);
			outSubs[i].numlines = numsegs;
			outSubs[i].firstline = segs.Size() - numsegs;
			outSubs[i].poly = NULL;
		}

		segCount = segs.Size ();
		outSegs = new seg_t[segCount];
		memcpy (outSegs, &segs[0], segCount*sizeof(seg_t));

		for (i = 0; i < segCount; ++i)
		{
			if (outSegs[i].PartnerSeg != NULL)
			{
				outSegs[i].PartnerSeg = &outSegs[Segs[(unsigned int)(size_t)outSegs[i].PartnerSeg-1].storedseg];
			}
		}
	}
	else
	{
		memcpy (outSubs, &Subsectors[0], subCount*sizeof(subsector_t));
		segCount = Segs.Size ();
		outSegs = new seg_t[segCount];
		for (i = 0; i < segCount; ++i)
		{
			const FPrivSeg *org = &Segs[SegList[i].SegNum];
			seg_t *out = &outSegs[i];

			out->v1 = outVerts + org->v1;
			out->v2 = outVerts + org->v2;
			out->backsector = org->backsector;
			out->frontsector = org->frontsector;
			out->linedef = Level.Lines + org->linedef;
			out->sidedef = Level.Sides + org->sidedef;
			out->PartnerSeg = NULL;
			out->bPolySeg = false;
		}
	}

	//Printf ("%i segs, %i nodes, %i subsectors\n", segCount, nodeCount, subCount);

	for (i = 0; i < Level.NumLines; ++i)
	{
		Level.Lines[i].v1 = outVerts + (size_t)Level.Lines[i].v1;
		Level.Lines[i].v2 = outVerts + (size_t)Level.Lines[i].v2;
	}
}
void FNodeBuilder::ExtractMini (FMiniBSP *bsp)
{
	unsigned int i;

	bsp->bDirty = false;
	bsp->Verts.Resize(Vertices.Size());
	for (i = 0; i < Vertices.Size(); ++i)
	{
		bsp->Verts[i].set(Vertices[i].x, Vertices[i].y);
	}

	bsp->Subsectors.Resize(Subsectors.Size());
	memset(&bsp->Subsectors[0], 0, Subsectors.Size() * sizeof(subsector_t));

	bsp->Nodes.Resize(Nodes.Size());
	memcpy(&bsp->Nodes[0], &Nodes[0], Nodes.Size()*sizeof(node_t));
	for (i = 0; i < Nodes.Size(); ++i)
	{
		D(Printf(PRINT_LOG, "Node %d:\n", i));
		// Go backwards because on 64-bit systems, both of the intchildren are
		// inside the first in-game child.
		for (int j = 1; j >= 0; --j)
		{
			if (bsp->Nodes[i].intchildren[j] & 0x80000000)
			{
				D(Printf(PRINT_LOG, "  subsector %d\n", bsp->Nodes[i].intchildren[j] & 0x7FFFFFFF));
				bsp->Nodes[i].children[j] = (uint8_t *)&bsp->Subsectors[bsp->Nodes[i].intchildren[j] & 0x7fffffff] + 1;
			}
			else
			{
				D(Printf(PRINT_LOG, "  node %d\n", bsp->Nodes[i].intchildren[j]));
				bsp->Nodes[i].children[j] = &bsp->Nodes[bsp->Nodes[i].intchildren[j]];
			}
		}
		for (int j = 0; j < 2; ++j)
		{
			for (int k = 0; k < 4; ++k)
			{
				bsp->Nodes[i].bbox[j][k] = FIXED2FLOAT(bsp->Nodes[i].nb_bbox[j][k]);
			}
		}
	}

	if (GLNodes)
	{
		TArray<glseg_t> glsegs;
		for (i = 0; i < Subsectors.Size(); ++i)
		{
			uint32_t numsegs = CloseSubsector (glsegs, i, &bsp->Verts[0]);
			bsp->Subsectors[i].numlines = numsegs;
			bsp->Subsectors[i].firstline = &bsp->Segs[bsp->Segs.Size() - numsegs];
		}
		bsp->Segs.Resize(glsegs.Size());
		for (i = 0; i < glsegs.Size(); ++i)
		{
			bsp->Segs[i] = *(seg_t *)&glsegs[i];
		}
	}
	else
	{
		memcpy(&bsp->Subsectors[0], &Subsectors[0], Subsectors.Size()*sizeof(subsector_t));
		bsp->Segs.Resize(Segs.Size());
		for (i = 0; i < Segs.Size(); ++i)
		{
			const FPrivSeg *org = &Segs[SegList[i].SegNum];
			seg_t *out = &bsp->Segs[i];

			D(Printf(PRINT_LOG, "Seg %d: v1(%d) -> v2(%d)\n", i, org->v1, org->v2));

			out->v1 = &bsp->Verts[org->v1];
			out->v2 = &bsp->Verts[org->v2];
			out->backsector = org->backsector;
			out->frontsector = org->frontsector;
			if (org->sidedef != int(NO_SIDE))
			{
				out->linedef = Level.Lines + org->linedef;
				out->sidedef = Level.Sides + org->sidedef;
			}
			else	// part of a miniseg
			{
				out->linedef = NULL;
				out->sidedef = NULL;
			}
		}
		for (i = 0; i < bsp->Subsectors.Size(); ++i)
		{
			bsp->Subsectors[i].firstline = &bsp->Segs[(size_t)bsp->Subsectors[i].firstline];
		}
	}
}