Ejemplo n.º 1
0
//
// DivideOneSeg
//
// Apply the partition line to the given seg, taking the necessary
// action (moving it into either the left list, right list, or
// splitting it).
//
// -AJA- I have rewritten this routine based on the EvalPartition
//       routine above (which I've also reworked, heavily).  I think
//       it is important that both these routines follow the exact
//       same logic when determining which segs should go left, right
//       or be split.
//
void DivideOneSeg(seg_t *cur, seg_t *part, 
    superblock_t *left_list, superblock_t *right_list,
    intersection_t ** cut_list)
{
  seg_t *new_seg;

  float_g x, y;

  /* get state of lines' relation to each other */
  float_g a = UtilPerpDist(part, cur->psx, cur->psy);
  float_g b = UtilPerpDist(part, cur->pex, cur->pey);

  boolean_g self_ref = cur->linedef ? cur->linedef->self_ref : FALSE;

  if (cur->source_line == part->source_line)
    a = b = 0;

  /* check for being on the same line */
  if (fabs(a) <= DIST_EPSILON && fabs(b) <= DIST_EPSILON)
  {
    AddIntersection(cut_list, cur->start, part, self_ref);
    AddIntersection(cut_list, cur->end,   part, self_ref);

    // this seg runs along the same line as the partition.  check
    // whether it goes in the same direction or the opposite.

    if (cur->pdx*part->pdx + cur->pdy*part->pdy < 0)
    {
      AddSegToSuper(left_list, cur);
    }
    else
    {
      AddSegToSuper(right_list, cur);
    }

    return;
  }

  /* check for right side */
  if (a > -DIST_EPSILON && b > -DIST_EPSILON)
  {
    if (a < DIST_EPSILON)
      AddIntersection(cut_list, cur->start, part, self_ref);
    else if (b < DIST_EPSILON)
      AddIntersection(cut_list, cur->end, part, self_ref);

    AddSegToSuper(right_list, cur);
    return;
  }
 
  /* check for left side */
  if (a < DIST_EPSILON && b < DIST_EPSILON)
  {
    if (a > -DIST_EPSILON)
      AddIntersection(cut_list, cur->start, part, self_ref);
    else if (b > -DIST_EPSILON)
      AddIntersection(cut_list, cur->end, part, self_ref);

    AddSegToSuper(left_list, cur);
    return;
  }
 
  // when we reach here, we have a and b non-zero and opposite sign,
  // hence this seg will be split by the partition line.
  
  ComputeIntersection(cur, part, a, b, &x, &y);

  new_seg = SplitSeg(cur, x, y);

  AddIntersection(cut_list, cur->end, part, self_ref);

  if (a < 0)
  {
    AddSegToSuper(left_list,  cur);
    AddSegToSuper(right_list, new_seg);
  }
  else
  {
    AddSegToSuper(right_list, cur);
    AddSegToSuper(left_list,  new_seg);
  }
}
Ejemplo n.º 2
0
// If there are any segs on the splitter that span more than two events, they
// must be split. Alien Vendetta is one example wad that is quite bad about
// having overlapping lines. If we skip this step, these segs will still be
// split later, but minisegs will erroneously be added for them, and partner
// seg information will be messed up in the generated tree.
void FNodeBuilder::FixSplitSharers ()
{
	D(printf("events:\n"));
	D(Events.PrintTree());
	for (unsigned int i = 0; i < SplitSharers.Size(); ++i)
	{
		DWORD seg = SplitSharers[i].Seg;
		int v2 = Segs[seg].v2;
		FEvent *event = Events.FindEvent (SplitSharers[i].Distance);
		FEvent *next;

		if (event == NULL)
		{ // Should not happen
			continue;
		}

		D(printf("Considering events on seg %d(%d[%d,%d]->%d[%d,%d]) [%g:%g]\n", seg,
			Segs[seg].v1,
			Vertices[Segs[seg].v1].x>>16,
			Vertices[Segs[seg].v1].y>>16,
			Segs[seg].v2,
			Vertices[Segs[seg].v2].x>>16,
			Vertices[Segs[seg].v2].y>>16,
			SplitSharers[i].Distance, event->Distance));

		if (SplitSharers[i].Forward)
		{
			event = Events.GetSuccessor (event);
			if (event == NULL)
			{
				continue;
			}
			next = Events.GetSuccessor (event);
		}
		else
		{
			event = Events.GetPredecessor (event);
			if (event == NULL)
			{
				continue;
			}
			next = Events.GetPredecessor (event);
		}

		while (event != NULL && next != NULL && event->Info.Vertex != v2)
		{
			D(printf("Forced split of seg %d(%d[%d,%d]->%d[%d,%d]) at %d(%d,%d):%g\n", seg,
				Segs[seg].v1,
				Vertices[Segs[seg].v1].x>>16,
				Vertices[Segs[seg].v1].y>>16,
				Segs[seg].v2,
				Vertices[Segs[seg].v2].x>>16,
				Vertices[Segs[seg].v2].y>>16,
				event->Info.Vertex,
				Vertices[event->Info.Vertex].x>>16,
				Vertices[event->Info.Vertex].y>>16,
				event->Distance));

			DWORD newseg = SplitSeg (seg, event->Info.Vertex, 1);

			Segs[newseg].next = Segs[seg].next;
			Segs[seg].next = newseg;

			DWORD partner = Segs[seg].partner;
			if (partner != DWORD_MAX)
			{
				int endpartner = SplitSeg (partner, event->Info.Vertex, 1);

				Segs[endpartner].next = Segs[partner].next;
				Segs[partner].next = endpartner;

				Segs[seg].partner = endpartner;
				//Segs[endpartner].partner = seg;
				Segs[partner].partner = newseg;

				assert (Segs[Segs[seg].partner].partner == seg);
				assert (Segs[Segs[newseg].partner].partner == newseg);
				assert (Segs[seg].v1 == Segs[endpartner].v2);
				assert (Segs[seg].v2 == Segs[endpartner].v1);
				assert (Segs[partner].v1 == Segs[newseg].v2);
				assert (Segs[partner].v2 == Segs[newseg].v1);
			}

			seg = newseg;
			if (SplitSharers[i].Forward)
			{
				event = next;
				next = Events.GetSuccessor (next);
			}
			else
			{
				event = next;
				next = Events.GetPredecessor (next);
			}
		}
	}
}
Ejemplo n.º 3
0
// If there are any segs on the splitter that span more than two events, they
// must be split. Alien Vendetta is one example wad that is quite bad about
// having overlapping lines. If we skip this step, these segs will still be
// split later, but minisegs will erroneously be added for them, and partner
// seg information will be messed up in the generated tree.
void FNodeBuilder::FixSplitSharers (const node_t &node)
{
	D(Printf(PRINT_LOG, "events:\n"));
	D(Events.PrintTree());
	for (unsigned int i = 0; i < SplitSharers.Size(); ++i)
	{
		DWORD seg = SplitSharers[i].Seg;
		int v2 = Segs[seg].v2;
		FEvent *event = Events.FindEvent (SplitSharers[i].Distance);
		FEvent *next;

		if (event == NULL)
		{ // Should not happen
			continue;
		}

		// Use the CRT's printf so the formatting matches ZDBSP's
		D(char buff[200]);
		D(sprintf(buff, "Considering events on seg %d(%d[%d,%d]->%d[%d,%d]) [%g:%g]\n", seg,
			Segs[seg].v1,
			Vertices[Segs[seg].v1].x>>16,
			Vertices[Segs[seg].v1].y>>16,
			Segs[seg].v2,
			Vertices[Segs[seg].v2].x>>16,
			Vertices[Segs[seg].v2].y>>16,
			SplitSharers[i].Distance, event->Distance));
		D(Printf(PRINT_LOG, "%s", buff));

		if (SplitSharers[i].Forward)
		{
			event = Events.GetSuccessor (event);
			if (event == NULL)
			{
				continue;
			}
			next = Events.GetSuccessor (event);
		}
		else
		{
			event = Events.GetPredecessor (event);
			if (event == NULL)
			{
				continue;
			}
			next = Events.GetPredecessor (event);
		}

		while (event != NULL && next != NULL && event->Info.Vertex != v2)
		{
			D(Printf(PRINT_LOG, "Forced split of seg %d(%d->%d) at %d(%d,%d)\n", seg,
				Segs[seg].v1, Segs[seg].v2,
				event->Info.Vertex,
				Vertices[event->Info.Vertex].x>>16,
				Vertices[event->Info.Vertex].y>>16));

			DWORD newseg = SplitSeg (seg, event->Info.Vertex, 1);

			Segs[newseg].next = Segs[seg].next;
			Segs[seg].next = newseg;

			DWORD partner = Segs[seg].partner;
			if (partner != DWORD_MAX)
			{
				int endpartner = SplitSeg (partner, event->Info.Vertex, 1);

				Segs[endpartner].next = Segs[partner].next;
				Segs[partner].next = endpartner;

				Segs[seg].partner = endpartner;
				Segs[partner].partner = newseg;
			}

			seg = newseg;
			if (SplitSharers[i].Forward)
			{
				event = next;
				next = Events.GetSuccessor (next);
			}
			else
			{
				event = next;
				next = Events.GetPredecessor (next);
			}
		}
	}
}
Ejemplo n.º 4
0
// If there are any segs on the splitter that span more than two events, they
// must be split. Alien Vendetta is one example wad that is quite bad about
// having overlapping lines. If we skip this step, these segs will still be
// split later, but minisegs will erroneously be added for them, and partner
// seg information will be messed up in the generated tree.
void FNodeBuilder::FixSplitSharers (const node_t &node)
{
	for (unsigned int i = 0; i < SplitSharers.Size(); ++i)
	{
		DWORD seg = SplitSharers[i].Seg;
		int v2 = Segs[seg].v2;
		FEvent *event = Events.FindEvent (SplitSharers[i].Distance);
		FEvent *next;

		if (event == NULL)
		{ // Should not happen
			continue;
		}

		if (SplitSharers[i].Forward)
		{
			event = Events.GetSuccessor (event);
			if (event == NULL)
			{
				continue;
			}
			next = Events.GetSuccessor (event);
		}
		else
		{
			event = Events.GetPredecessor (event);
			if (event == NULL)
			{
				continue;
			}
			next = Events.GetPredecessor (event);
		}

		while (event != NULL && next != NULL && event->Info.Vertex != v2)
		{
			D(Printf(PRINT_LOG, "Forced split of seg %d(%d->%d) at %d(%d,%d)\n", seg,
				Segs[seg].v1, Segs[seg].v2,
				event->Info.Vertex,
				Vertices[event->Info.Vertex].x>>16,
				Vertices[event->Info.Vertex].y>>16));

			DWORD newseg = SplitSeg (seg, event->Info.Vertex, 1);

			Segs[newseg].next = Segs[seg].next;
			Segs[seg].next = newseg;

			DWORD partner = Segs[seg].partner;
			if (partner != DWORD_MAX)
			{
				int endpartner = SplitSeg (partner, event->Info.Vertex, 1);

				Segs[endpartner].next = Segs[partner].next;
				Segs[partner].next = endpartner;

				Segs[seg].partner = endpartner;
				Segs[partner].partner = newseg;
			}

			seg = newseg;
			if (SplitSharers[i].Forward)
			{
				event = next;
				next = Events.GetSuccessor (next);
			}
			else
			{
				event = next;
				next = Events.GetPredecessor (next);
			}
		}
	}
}