static seg_t *FindFastSeg(superblock_t *seg_list, const bbox_t *bbox) { seg_t *best_H = NULL; seg_t *best_V = NULL; int mid_x = (bbox->minx + bbox->maxx) / 2; int mid_y = (bbox->miny + bbox->maxy) / 2; EvaluateFastWorker(seg_list, &best_H, &best_V, mid_x, mid_y); int H_cost = -1; int V_cost = -1; if (best_H) H_cost = EvalPartition(seg_list, best_H, 99999999); if (best_V) V_cost = EvalPartition(seg_list, best_V, 99999999); # if DEBUG_PICKNODE PrintDebug("FindFastSeg: best_H=%p (cost %d) | best_V=%p (cost %d)\n", best_H, H_cost, best_V, V_cost); # endif if (H_cost < 0 && V_cost < 0) return NULL; if (H_cost < 0) return best_V; if (V_cost < 0) return best_H; return (V_cost < H_cost) ? best_V : best_H; }
/* returns FALSE if cancelled */ static int PickNodeWorker(superblock_t *part_list, superblock_t *seg_list, seg_t ** best, int *best_cost, int *progress, int prog_step) { seg_t *part; int num; int cost; /* use each Seg as partition */ for (part=part_list->segs; part; part = part->next) { if (cur_comms->cancelled) return FALSE; # if DEBUG_PICKNODE PrintDebug("PickNode: %sSEG %p sector=%d (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", part->linedef ? "" : "MINI", part, part->sector ? part->sector->index : -1, part->start->x, part->start->y, part->end->x, part->end->y); # endif /* something for the user to look at */ (*progress) += 1; if ((*progress % prog_step) == 0) { cur_comms->build_pos++; DisplaySetBar(1, cur_comms->build_pos); DisplaySetBar(2, cur_comms->file_pos + cur_comms->build_pos / 100); } /* ignore minisegs as partition candidates */ if (! part->linedef) continue; cost = EvalPartition(seg_list, part, *best_cost); /* seg unsuitable or too costly ? */ if (cost < 0 || cost >= *best_cost) continue; /* we have a new better choice */ (*best_cost) = cost; /* remember which Seg */ (*best) = part; } DisplayTicker(); /* recursively handle sub-blocks */ for (num=0; num < 2; num++) { if (part_list->subs[num]) PickNodeWorker(part_list->subs[num], seg_list, best, best_cost, progress, prog_step); } return TRUE; }
// // PickNode // // Find the best seg in the seg_list to use as a partition line. // seg_t *PickNode(superblock_t *seg_list, int depth, node_t ** stale_nd, int *stale_opposite) { seg_t *best=NULL; int best_cost=INT_MAX; int progress=0; int prog_step=1<<24; int build_step=0; # if DEBUG_PICKNODE PrintDebug("PickNode: BEGUN (depth %d)\n", depth); # endif /* compute info for showing progress */ if (depth <= 6) { static int depth_counts[7] = { 248, 100, 30, 10, 6, 4, 2 }; int total = seg_list->real_num + seg_list->mini_num; build_step = depth_counts[depth]; prog_step = 1 + ((total - 1) / build_step); if (total / prog_step < build_step) { cur_comms->build_pos += build_step - total / prog_step; build_step = total / prog_step; DisplaySetBar(1, cur_comms->build_pos); DisplaySetBar(2, cur_comms->file_pos + cur_comms->build_pos / 100); } } DisplayTicker(); /* -AJA- another (optional) optimisation, when building just the GL * nodes. We assume that the original nodes are reasonably * good choices, and re-use them as much as possible, saving * *heaps* of time on really large levels. */ if (*stale_nd && seg_list->real_num >= SEG_REUSE_THRESHHOLD) { best = FindSegFromStaleNode(seg_list, *stale_nd, stale_opposite); # if DEBUG_PICKNODE PrintDebug("PickNode: Trying stale node %p\n", best); # endif if (best && EvalPartition(seg_list, best, best_cost) < 0) { best = NULL; # if DEBUG_PICKNODE PrintDebug("PickNode: Stale node unsuitable !\n"); # endif } if (best) { /* update progress */ cur_comms->build_pos += build_step; DisplaySetBar(1, cur_comms->build_pos); DisplaySetBar(2, cur_comms->file_pos + cur_comms->build_pos / 100); # if DEBUG_PICKNODE PrintDebug("PickNode: Using Stale node (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", best->start->x, best->start->y, best->end->x, best->end->y); # endif return best; } } (*stale_nd) = NULL; if (FALSE == PickNodeWorker(seg_list, seg_list, &best, &best_cost, &progress, prog_step)) { /* hack here : BuildNodes will detect the cancellation */ return NULL; } # if DEBUG_PICKNODE if (! best) { PrintDebug("PickNode: NO BEST FOUND !\n"); } else { PrintDebug("PickNode: Best has score %d.%02d (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", best_cost / 100, best_cost % 100, best->start->x, best->start->y, best->end->x, best->end->y); } # endif /* all finished, return best Seg */ return best; }