Beispiel #1
0
void PruneSectors(void)
{
  int i;
  int new_num;

  DisplayTicker();

  // scan all sectors
  for (i=0, new_num=0; i < num_sectors; i++)
  {
    sector_t *S = lev_sectors[i];

    if (S->ref_count < 0)
      InternalError("Sector %d ref_count is %d", i, S->ref_count);
    
    if (S->ref_count == 0)
    {
      UtilFree(S);
      continue;
    }

    S->index = new_num;
    lev_sectors[new_num++] = S;
  }

  if (new_num < num_sectors)
  {
    PrintVerbose("Pruned %d unused sectors\n", num_sectors - new_num);
    num_sectors = new_num;
  }

  if (new_num == 0)
    FatalError("Couldn't find any Sectors");
}
Beispiel #2
0
void DetectDuplicateSidedefs(void)
{
  int i;
  uint16_g *array = UtilCalloc(num_sidedefs * sizeof(uint16_g));

  DisplayTicker();

  // sort array of indices
  for (i=0; i < num_sidedefs; i++)
    array[i] = i;
  
  qsort(array, num_sidedefs, sizeof(uint16_g), SidedefCompare);

  // now mark them off
  for (i=0; i < num_sidedefs - 1; i++)
  {
    // duplicate ?
    if (SidedefCompare(array + i, array + i+1) == 0)
    {
      sidedef_t *A = lev_sidedefs[array[i]];
      sidedef_t *B = lev_sidedefs[array[i+1]];

      // found a duplicate !
      B->equiv = A->equiv ? A->equiv : A;
    }
  }

  UtilFree(array);
}
Beispiel #3
0
//
// ReadLumpData
//
static void ReadLumpData(lump_t *lump)
{
  size_t len;

  cur_comms->file_pos++;
  DisplaySetBar(1, cur_comms->file_pos);
  DisplayTicker();

# if DEBUG_LUMP
  PrintDebug("Reading... %s (%d)\n", lump->name, lump->length);
# endif
  
  if (lump->length == 0)
    return;

  lump->data = UtilCalloc(lump->length);

  fseek(in_file, lump->start, SEEK_SET);

  len = fread(lump->data, lump->length, 1, in_file);

  if (len != 1)
  {
    if (wad.current_level)
      PrintWarn("Trouble reading lump '%s' in %s\n",
          lump->name, wad.current_level->name);
    else
      PrintWarn("Trouble reading lump '%s'\n", lump->name);
  }

  lump->flags &= ~LUMP_READ_ME;
}
Beispiel #4
0
//
// ReadDirEntry
//
static void ReadDirEntry(void)
{
  size_t len;
  raw_wad_entry_t entry;
  lump_t *lump;
  
  DisplayTicker();

  len = fread(&entry, sizeof(entry), 1, in_file);

  if (len != 1)
    FatalError("Trouble reading wad directory");

  lump = NewLump(UtilStrNDup(entry.name, 8));

  lump->start  = UINT32(entry.start);
  lump->length = UINT32(entry.length);

# if DEBUG_DIR
  PrintDebug("Read dir... %s\n", lump->name);
# endif

  // link it in
  lump->next = NULL;
  lump->prev = wad.dir_tail;

  if (wad.dir_tail)
    wad.dir_tail->next = lump;
  else
    wad.dir_head = lump;

  wad.dir_tail = lump;
}
Beispiel #5
0
void CalculateWallTips(void)
{
  int i;
  float_g x1;
  float_g y1;
  float_g x2;
  float_g y2;

  sector_t *left;
  sector_t *right;

  DisplayTicker();

  for (i=0; i < num_linedefs; i++)
  {
    linedef_t *line = lev_linedefs[i];

    if (line->self_ref && cur_info->skip_self_ref)
      continue;

    x1 = line->start->x;
    y1 = line->start->y;
    x2 = line->end->x;
    y2 = line->end->y;

    left  = (line->left)  ? line->left->sector  : NULL;
    right = (line->right) ? line->right->sector : NULL;
    
    VertexAddWallTip(line->start, x2-x1, y2-y1, left, right);
    VertexAddWallTip(line->end,   x1-x2, y1-y2, right, left);
  }
 
# if DEBUG_WALLTIPS
  for (i=0; i < num_vertices; i++)
  {
    vertex_t *vert = LookupVertex(i);
    wall_tip_t *tip;

    PrintDebug("WallTips for vertex %d:\n", i);

    for (tip=vert->tip_set; tip; tip=tip->next)
    {
      PrintDebug("  Angle=%1.1f left=%d right=%d\n", tip->angle,
        tip->left ? tip->left->index : -1,
        tip->right ? tip->right->index : -1);
    }
  }
# endif
}
Beispiel #6
0
//
// WriteLumpData
//
static void WriteLumpData(lump_t *lump)
{
  size_t len;
  int align_size;

  cur_comms->file_pos++;
  DisplaySetBar(1, cur_comms->file_pos);
  DisplayTicker();

# if DEBUG_LUMP
  if (lump->flags & LUMP_COPY_ME)
    PrintDebug("Copying... %s (%d)\n", lump->name, lump->length);
  else
    PrintDebug("Writing... %s (%d)\n", lump->name, lump->length);
# endif
  
  if (ftell(out_file) != lump->new_start)
    PrintWarn("Consistency failure writing %s (%08lX, %08X\n", 
      lump->name, ftell(out_file), lump->new_start);
 
  if (lump->length == 0)
    return;

  if (lump->flags & LUMP_COPY_ME)
  {
    lump->data = UtilCalloc(lump->length);

    fseek(in_file, lump->start, SEEK_SET);

    len = fread(lump->data, lump->length, 1, in_file);

    if (len != 1)
      PrintWarn("Trouble reading lump %s to copy\n", lump->name);
  }

  len = fwrite(lump->data, lump->length, 1, out_file);
   
  if (len != 1)
    PrintWarn("Trouble writing lump %s\n", lump->name);
  
  align_size = ALIGN_LEN(lump->length) - lump->length;

  if (align_size > 0)
    fwrite(align_filler, align_size, 1, out_file);

  UtilFree(lump->data);

  lump->data = NULL;
}
Beispiel #7
0
void DetectOverlappingLines(void)
{
  // Algorithm:
  //   Sort all lines by left-most vertex.
  //   Overlapping lines will then be near each other in this set.
  //   Note: does not detect partially overlapping lines.

  int i;
  int *array = UtilCalloc(num_linedefs * sizeof(int));
  int count = 0;

  DisplayTicker();

  // sort array of indices
  for (i=0; i < num_linedefs; i++)
    array[i] = i;
  
  qsort(array, num_linedefs, sizeof(int), LineStartCompare);

  for (i=0; i < num_linedefs - 1; i++)
  {
    int j;

    for (j = i+1; j < num_linedefs; j++)
    {
      if (LineStartCompare(array + i, array + j) != 0)
        break;

      if (LineEndCompare(array + i, array + j) == 0)
      {
        linedef_t *A = lev_linedefs[array[i]];
        linedef_t *B = lev_linedefs[array[j]];

        // found an overlap !
        B->overlap = A->overlap ? A->overlap : A;

        count++;
      }
    }
  }

  if (count > 0)
  {
      PrintVerbose("Detected %d overlapped linedefs\n", count);
  }

  UtilFree(array);
}
Beispiel #8
0
void PruneSidedefs(void)
{
  int i;
  int new_num;
  int unused = 0;

  DisplayTicker();

  // scan all sidedefs
  for (i=0, new_num=0; i < num_sidedefs; i++)
  {
    sidedef_t *S = lev_sidedefs[i];

    if (S->ref_count < 0)
      InternalError("Sidedef %d ref_count is %d", i, S->ref_count);
    
    if (S->ref_count == 0)
    {
      if (S->sector)
        S->sector->ref_count--;

      if (S->equiv == NULL)
        unused++;

      UtilFree(S);
      continue;
    }

    S->index = new_num;
    lev_sidedefs[new_num++] = S;
  }

  if (new_num < num_sidedefs)
  {
    int dup_num = num_sidedefs - new_num - unused;

    if (unused > 0)
      PrintVerbose("Pruned %d unused sidedefs\n", unused);

    if (dup_num > 0)
      PrintVerbose("Pruned %d duplicate sidedefs\n", dup_num);

    num_sidedefs = new_num;
  }

  if (new_num == 0)
    FatalError("Couldn't find any Sidedefs");
}
Beispiel #9
0
void PruneVertices(void)
{
  int i;
  int new_num;
  int unused = 0;

  DisplayTicker();

  // scan all vertices
  for (i=0, new_num=0; i < num_vertices; i++)
  {
    vertex_t *V = lev_vertices[i];

    if (V->ref_count < 0)
      InternalError("Vertex %d ref_count is %d", i, V->ref_count);
    
    if (V->ref_count == 0)
    {
      if (V->equiv == NULL)
        unused++;

      UtilFree(V);
      continue;
    }

    V->index = new_num;
    lev_vertices[new_num++] = V;
  }

  if (new_num < num_vertices)
  {
    int dup_num = num_vertices - new_num - unused;

    if (unused > 0)
      PrintVerbose("Pruned %d unused vertices "
        "(this is normal if the nodes were built before)\n", unused);

    if (dup_num > 0)
      PrintVerbose("Pruned %d duplicate vertices\n", dup_num);

    num_vertices = new_num;
  }

  if (new_num == 0)
    FatalError("Couldn't find any Vertices");
 
  num_normal_vert = num_vertices;
}
Beispiel #10
0
//
// WriteDirEntry
//
static void WriteDirEntry(lump_t *lump)
{
  size_t len;
  raw_wad_entry_t entry;

  DisplayTicker();

  strncpy(entry.name, lump->name, 8);

  entry.start  = UINT32(lump->new_start);
  entry.length = UINT32(lump->length);

  len = fwrite(&entry, sizeof(entry), 1, out_file);

  if (len != 1)
    PrintWarn("Trouble writing wad directory\n");
}
Beispiel #11
0
//
// PickNode
//
// Find the best seg in the seg_list to use as a partition line.
//
seg_t *PickNode(superblock_t *seg_list, int depth, const bbox_t *bbox)
{
  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 (cur_info->fast && seg_list->real_num >= SEG_FAST_THRESHHOLD)
  {
#   if DEBUG_PICKNODE
    PrintDebug("PickNode: Looking for Fast node...\n");
#   endif

    best = FindFastSeg(seg_list, bbox);

    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 Fast 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;
    }
  }

  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;
}
Beispiel #12
0
/* 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;
}
Beispiel #13
0
void PruneLinedefs(void)
{
  int i;
  int new_num;

  DisplayTicker();

  // scan all linedefs
  for (i=0, new_num=0; i < num_linedefs; i++)
  {
    linedef_t *L = lev_linedefs[i];

    // handle duplicated vertices
    while (L->start->equiv)
    {
      L->start->ref_count--;
      L->start = L->start->equiv;
      L->start->ref_count++;
    }

    while (L->end->equiv)
    {
      L->end->ref_count--;
      L->end = L->end->equiv;
      L->end->ref_count++;
    }

    // handle duplicated sidedefs
    while (L->right && L->right->equiv)
    {
      L->right->ref_count--;
      L->right = L->right->equiv;
      L->right->ref_count++;
    }

    while (L->left && L->left->equiv)
    {
      L->left->ref_count--;
      L->left = L->left->equiv;
      L->left->ref_count++;
    }

    // remove zero length lines
    if (L->zero_len)
    {
      L->start->ref_count--;
      L->end->ref_count--;

      UtilFree(L);
      continue;
    }

    L->index = new_num;
    lev_linedefs[new_num++] = L;
  }

  if (new_num < num_linedefs)
  {
    PrintVerbose("Pruned %d zero-length linedefs\n", num_linedefs - new_num);
    num_linedefs = new_num;
  }

  if (new_num == 0)
    FatalError("Couldn't find any Linedefs");
}
Beispiel #14
0
//
// ProcessDirEntry
//
static void ProcessDirEntry(lump_t *lump)
{
  DisplayTicker();

  // ignore previous GL lump info
  if (CheckGLLumpName(lump->name))
  {
#   if DEBUG_DIR
    PrintDebug("Discarding previous GL info: %s\n", lump->name);
#   endif

    FreeLump(lump);
    wad.num_entries--;

    return;
  }

  // --- LEVEL MARKERS ---

  if (CheckLevelName(lump->name))
  {
    /* NOTE !  Level marks can have data (in Hexen anyway) */
    if (cur_info->load_all)
      lump->flags |= LUMP_READ_ME;
    else
      lump->flags |= LUMP_COPY_ME;

    // OK, start a new level

    lump->lev_info = NewLevel(0);

    wad.current_level = lump;

#   if DEBUG_DIR
    PrintDebug("Process dir... %s :\n", lump->name);
#   endif

    // link it in
    lump->next = NULL;
    lump->prev = wad.dir_tail;

    if (wad.dir_tail)
      wad.dir_tail->next = lump;
    else
      wad.dir_head = lump;

    wad.dir_tail = lump;

    return;
  }

  // --- LEVEL LUMPS ---

  if (wad.current_level)
  {
    if (CheckLevelLumpName(lump->name))
    {
      // check for duplicates
      if (FindLevelLump(lump->name))
      {
        PrintWarn("Duplicate entry '%s' ignored in %s\n",
            lump->name, wad.current_level->name);

        FreeLump(lump);
        wad.num_entries--;

        return;
      }

#     if DEBUG_DIR
      PrintDebug("Process dir... |--- %s\n", lump->name);
#     endif

      // mark it to be loaded
      lump->flags |= LUMP_READ_ME;
    
      // link it in
      lump->next = wad.current_level->lev_info->children;
      lump->prev = NULL;

      if (lump->next)
        lump->next->prev = lump;

      wad.current_level->lev_info->children = lump;
      return;
    }
      
    // OK, non-level lump.  End the previous level.

    wad.current_level = NULL;
  }

  // --- ORDINARY LUMPS ---

# if DEBUG_DIR
  PrintDebug("Process dir... %s\n", lump->name);
# endif

  if (CheckLevelLumpName(lump->name))
    PrintWarn("Level lump '%s' found outside any level\n", lump->name);

  // maybe load data
  if (cur_info->load_all)
    lump->flags |= LUMP_READ_ME;
  else
    lump->flags |= LUMP_COPY_ME;

  // link it in
  lump->next = NULL;
  lump->prev = wad.dir_tail;

  if (wad.dir_tail)
    wad.dir_tail->next = lump;
  else
    wad.dir_head = lump;

  wad.dir_tail = lump;
}