// // AddMinisegs // void AddMinisegs(seg_t *part, superblock_t *left_list, superblock_t *right_list, intersection_t *cut_list) { intersection_t *cur, *next; seg_t *seg, *buddy; if (! cut_list) return; # if DEBUG_CUTLIST PrintDebug("CUT LIST:\n"); PrintDebug("PARTITION: (%1.1f,%1.1f) += (%1.1f,%1.1f)\n", part->psx, part->psy, part->pdx, part->pdy); for (cur=cut_list; cur; cur=cur->next) { PrintDebug(" Vertex %8X (%1.1f,%1.1f) Along %1.2f [%d/%d] %s\n", cur->vertex->index, cur->vertex->x, cur->vertex->y, cur->along_dist, cur->before ? cur->before->index : -1, cur->after ? cur->after->index : -1, cur->self_ref ? "SELFREF" : ""); } # endif // STEP 1: fix problems the intersection list... cur = cut_list; next = cur->next; while (cur && next) { float_g len = next->along_dist - cur->along_dist; if (len < -0.1) InternalError("Bad order in intersect list: %1.3f > %1.3f\n", cur->along_dist, next->along_dist); if (len > 0.2) { cur = next; next = cur->next; continue; } if (len > DIST_EPSILON) { PrintMiniWarn("Skipping very short seg (len=%1.3f) near (%1.1f,%1.1f)\n", len, cur->vertex->x, cur->vertex->y); } // merge the two intersections into one # if DEBUG_CUTLIST PrintDebug("Merging cut (%1.0f,%1.0f) [%d/%d] with %p (%1.0f,%1.0f) [%d/%d]\n", cur->vertex->x, cur->vertex->y, cur->before ? cur->before->index : -1, cur->after ? cur->after->index : -1, next->vertex, next->vertex->x, next->vertex->y, next->before ? next->before->index : -1, next->after ? next->after->index : -1); # endif if (cur->self_ref && !next->self_ref) { if (cur->before && next->before) cur->before = next->before; if (cur->after && next->after) cur->after = next->after; cur->self_ref = FALSE; } if (!cur->before && next->before) cur->before = next->before; if (!cur->after && next->after) cur->after = next->after; # if DEBUG_CUTLIST PrintDebug("---> merged (%1.0f,%1.0f) [%d/%d] %s\n", cur->vertex->x, cur->vertex->y, cur->before ? cur->before->index : -1, cur->after ? cur->after->index : -1, cur->self_ref ? "SELFREF" : ""); # endif // free the unused cut cur->next = next->next; next->next = quick_alloc_cuts; quick_alloc_cuts = next; next = cur->next; } // STEP 2: find connections in the intersection list... for (cur = cut_list; cur && cur->next; cur = cur->next) { next = cur->next; if (!cur->after && !next->before) continue; // check for some nasty OPEN/CLOSED or CLOSED/OPEN cases if (cur->after && !next->before) { if (!cur->self_ref && !cur->after->warned_unclosed) { PrintMiniWarn("Sector #%d is unclosed near (%1.1f,%1.1f)\n", cur->after->index, (cur->vertex->x + next->vertex->x) / 2.0, (cur->vertex->y + next->vertex->y) / 2.0); cur->after->warned_unclosed = 1; } continue; } else if (!cur->after && next->before) { if (!next->self_ref && !next->before->warned_unclosed) { PrintMiniWarn("Sector #%d is unclosed near (%1.1f,%1.1f)\n", next->before->index, (cur->vertex->x + next->vertex->x) / 2.0, (cur->vertex->y + next->vertex->y) / 2.0); next->before->warned_unclosed = 1; } continue; } // righteo, here we have definite open space. // do a sanity check on the sectors (just for good measure). if (cur->after != next->before) { if (!cur->self_ref && !next->self_ref) PrintMiniWarn("Sector mismatch: #%d (%1.1f,%1.1f) != #%d (%1.1f,%1.1f)\n", cur->after->index, cur->vertex->x, cur->vertex->y, next->before->index, next->vertex->x, next->vertex->y); // choose the non-self-referencing sector when we can if (cur->self_ref && !next->self_ref) { cur->after = next->before; } } // create the miniseg pair seg = NewSeg(); buddy = NewSeg(); seg->partner = buddy; buddy->partner = seg; seg->start = cur->vertex; seg->end = next->vertex; buddy->start = next->vertex; buddy->end = cur->vertex; // leave 'linedef' field as NULL. // leave 'side' as zero too (not needed for minisegs). seg->sector = buddy->sector = cur->after; seg->index = buddy->index = -1; seg->source_line = buddy->source_line = part->linedef; RecomputeSeg(seg); RecomputeSeg(buddy); // add the new segs to the appropriate lists AddSegToSuper(right_list, seg); AddSegToSuper(left_list, buddy); # if DEBUG_CUTLIST PrintDebug("AddMiniseg: %p RIGHT sector %d (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", seg, seg->sector ? seg->sector->index : -1, seg->start->x, seg->start->y, seg->end->x, seg->end->y); PrintDebug("AddMiniseg: %p LEFT sector %d (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", buddy, buddy->sector ? buddy->sector->index : -1, buddy->start->x, buddy->start->y, buddy->end->x, buddy->end->y); # endif } // free intersection structures into quick-alloc list while (cut_list) { cur = cut_list; cut_list = cur->next; cur->next = quick_alloc_cuts; quick_alloc_cuts = cur; } }
void TestForWindowEffect(linedef_t *L) { // cast a line horizontally or vertically and see what we hit. // OUCH, we have to iterate over all linedefs. int i; float_g mx = (L->start->x + L->end->x) / 2.0; float_g my = (L->start->y + L->end->y) / 2.0; float_g dx = L->end->x - L->start->x; float_g dy = L->end->y - L->start->y; int cast_horiz = fabs(dx) < fabs(dy) ? 1 : 0; float_g back_dist = 999999.0; sector_t * back_open = NULL; int back_line = -1; float_g front_dist = 999999.0; sector_t * front_open = NULL; int front_line = -1; for (i=0; i < num_linedefs; i++) { linedef_t *N = lev_linedefs[i]; float_g dist; boolean_g is_front; sidedef_t *hit_side; float_g dx2, dy2; if (N == L || N->zero_len || N->overlap) continue; if (cast_horiz) { dx2 = N->end->x - N->start->x; dy2 = N->end->y - N->start->y; if (fabs(dy2) < DIST_EPSILON) continue; if ((MAX(N->start->y, N->end->y) < my - DIST_EPSILON) || (MIN(N->start->y, N->end->y) > my + DIST_EPSILON)) continue; dist = (N->start->x + (my - N->start->y) * dx2 / dy2) - mx; is_front = ((dy > 0) == (dist > 0)) ? TRUE : FALSE; dist = fabs(dist); if (dist < DIST_EPSILON) // too close (overlapping lines ?) continue; hit_side = ((dy > 0) ^ (dy2 > 0) ^ !is_front) ? N->right : N->left; } else /* vert */ { dx2 = N->end->x - N->start->x; dy2 = N->end->y - N->start->y; if (fabs(dx2) < DIST_EPSILON) continue; if ((MAX(N->start->x, N->end->x) < mx - DIST_EPSILON) || (MIN(N->start->x, N->end->x) > mx + DIST_EPSILON)) continue; dist = (N->start->y + (mx - N->start->x) * dy2 / dx2) - my; is_front = ((dx > 0) != (dist > 0)) ? TRUE : FALSE; dist = fabs(dist); hit_side = ((dx > 0) ^ (dx2 > 0) ^ !is_front) ? N->right : N->left; } if (dist < DIST_EPSILON) // too close (overlapping lines ?) continue; if (is_front) { if (dist < front_dist) { front_dist = dist; front_open = hit_side ? hit_side->sector : NULL; front_line = i; } } else { if (dist < back_dist) { back_dist = dist; back_open = hit_side ? hit_side->sector : NULL; back_line = i; } } } #if DEBUG_WINDOW_FX PrintDebug("back line: %d back dist: %1.1f back_open: %s\n", back_line, back_dist, back_open ? "OPEN" : "CLOSED"); PrintDebug("front line: %d front dist: %1.1f front_open: %s\n", front_line, front_dist, front_open ? "OPEN" : "CLOSED"); #endif if (back_open && front_open && L->right->sector == front_open) { L->window_effect = back_open; PrintMiniWarn("Linedef #%d seems to be a One-Sided Window (back faces sector #%d).\n", L->index, back_open->index); } }