1
//------------------------------------------------------------------------
2
// LEVEL : Level structure read/write functions.
3
//------------------------------------------------------------------------
5
// GL-Node Viewer (C) 2004-2007 Andrew Apted
7
// This program is free software; you can redistribute it and/or
8
// modify it under the terms of the GNU General Public License
9
// as published by the Free Software Foundation; either version 2
10
// of the License, or (at your option) any later version.
12
// This program is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License for more details.
17
//------------------------------------------------------------------------
19
// this includes everything we need
26
// per-level variables
31
#define LEVELARRAY(TYPE, BASEVAR, NAMESTR) \
32
container_tp<TYPE> BASEVAR(NAMESTR);
34
LEVELARRAY(vertex_c, lev_vertices, "vertex")
35
LEVELARRAY(vertex_c, lev_gl_verts, "gl_vert")
36
LEVELARRAY(linedef_c, lev_linedefs, "linedef")
37
LEVELARRAY(sidedef_c, lev_sidedefs, "sidedef")
38
LEVELARRAY(sector_c, lev_sectors, "sector")
39
LEVELARRAY(thing_c, lev_things, "thing")
40
LEVELARRAY(seg_c, lev_segs, "seg")
41
LEVELARRAY(subsec_c, lev_subsecs, "subsector")
42
LEVELARRAY(node_c, lev_nodes, "node")
45
/* ----- reading routines ------------------------------ */
47
static const uint8_g *lev_v2_magic = (uint8_g *)"gNd2";
48
static const uint8_g *lev_v3_magic = (uint8_g *)"gNd3";
51
void GetLinedefsHexen(wad_c *base);
52
void GetThingsHexen(wad_c *base);
54
vertex_c::vertex_c(int _idx, const raw_vertex_t *raw)
58
x = (double) SINT16(raw->x);
59
y = (double) SINT16(raw->y);
62
vertex_c::vertex_c(int _idx, const raw_v2_vertex_t *raw)
66
x = (double) SINT32(raw->x) / 65536.0;
67
y = (double) SINT32(raw->y) / 65536.0;
77
void GetVertices(wad_c *base)
79
lump_c *lump = base->FindLumpInLevel("VERTEXES");
84
base->CacheLump(lump);
85
count = lump->length / sizeof(raw_vertex_t);
89
PrintDebug("GetVertices: num = %d\n", count);
92
if (!lump || count == 0)
93
FatalError("Couldn't find any Vertices");
95
lev_vertices.Allocate(count);
97
raw_vertex_t *raw = (raw_vertex_t *) lump->data;
99
for (int i = 0; i < count; i++, raw++)
101
lev_vertices.Set(i, new vertex_c(i, raw));
108
void GetV2Verts(const uint8_g *data, int length)
110
int count = length / sizeof(raw_v2_vertex_t);
112
lev_gl_verts.Allocate(count);
114
raw_v2_vertex_t *raw = (raw_v2_vertex_t *) data;
116
for (int i = 0; i < count; i++, raw++)
118
lev_gl_verts.Set(i, new vertex_c(i, raw));
125
void GetGLVerts(wad_c *base)
127
lump_c *lump = base->FindLumpInLevel("GL_VERT");
130
PrintDebug("GetVertices: num = %d\n", count);
134
FatalError("Couldn't find any GL Vertices");
136
base->CacheLump(lump);
138
if (lump->length >= 4 && memcmp(lump->data, lev_v2_magic, 4) == 0)
140
GetV2Verts((uint8_g *)lump->data + 4, lump->length - 4);
144
int count = lump->length / sizeof(raw_vertex_t);
146
lev_gl_verts.Allocate(count);
148
raw_vertex_t *raw = (raw_vertex_t *) lump->data;
150
for (int i = 0; i < count; i++, raw++)
152
lev_gl_verts.Set(i, new vertex_c(i, raw));
156
sector_c::sector_c(int _idx, const raw_sector_t *raw)
160
floor_h = SINT16(raw->floor_h);
161
ceil_h = SINT16(raw->ceil_h);
163
memcpy(floor_tex, raw->floor_tex, sizeof(floor_tex));
164
memcpy(ceil_tex, raw->ceil_tex, sizeof(ceil_tex));
166
light = UINT16(raw->light);
167
special = UINT16(raw->special);
168
tag = SINT16(raw->tag);
171
sector_c::~sector_c()
178
void GetSectors(wad_c *base)
181
lump_c *lump = base->FindLumpInLevel("SECTORS");
185
base->CacheLump(lump);
186
count = lump->length / sizeof(raw_sector_t);
189
if (!lump || count == 0)
190
FatalError("Couldn't find any Sectors");
193
PrintDebug("GetSectors: num = %d\n", count);
196
lev_sectors.Allocate(count);
198
raw_sector_t *raw = (raw_sector_t *) lump->data;
200
for (int i = 0; i < count; i++, raw++)
202
lev_sectors.Set(i, new sector_c(i, raw));
206
thing_c::thing_c(int _idx, const raw_thing_t *raw)
213
type = UINT16(raw->type);
214
options = UINT16(raw->options);
217
thing_c::thing_c(int _idx, const raw_hexen_thing_t *raw)
224
type = UINT16(raw->type);
225
options = UINT16(raw->options);
235
void GetThings(wad_c *base)
239
GetThingsHexen(base);
244
lump_c *lump = base->FindLumpInLevel("THINGS");
248
base->CacheLump(lump);
249
count = lump->length / sizeof(raw_thing_t);
252
if (!lump || count == 0)
254
// Note: no error if no things exist, even though technically a map
255
// will be unplayable without the player starts.
256
PrintWarn("Couldn't find any Things");
261
PrintDebug("GetThings: num = %d\n", count);
264
lev_things.Allocate(count);
266
raw_thing_t *raw = (raw_thing_t *) lump->data;
268
for (int i = 0; i < count; i++, raw++)
270
lev_things.Set(i, new thing_c(i, raw));
277
void GetThingsHexen(wad_c *base)
280
lump_c *lump = base->FindLumpInLevel("THINGS");
284
base->CacheLump(lump);
285
count = lump->length / sizeof(raw_hexen_thing_t);
288
if (!lump || count == 0)
290
// Note: no error if no things exist, even though technically a map
291
// will be unplayable without the player starts.
292
PrintWarn("Couldn't find any Things");
297
PrintDebug("GetThingsHexen: num = %d\n", count);
300
lev_things.Allocate(count);
302
raw_hexen_thing_t *raw = (raw_hexen_thing_t *) lump->data;
304
for (int i = 0; i < count; i++, raw++)
306
lev_things.Set(i, new thing_c(i, raw));
310
sidedef_c::sidedef_c(int _idx, const raw_sidedef_t *raw)
314
sector = (SINT16(raw->sector) == -1) ? NULL :
315
lev_sectors.Get(UINT16(raw->sector));
317
x_offset = SINT16(raw->x_offset);
318
y_offset = SINT16(raw->y_offset);
320
memcpy(upper_tex, raw->upper_tex, sizeof(upper_tex));
321
memcpy(lower_tex, raw->lower_tex, sizeof(lower_tex));
322
memcpy(mid_tex, raw->mid_tex, sizeof(mid_tex));
325
sidedef_c::~sidedef_c()
332
void GetSidedefs(wad_c *base)
335
lump_c *lump = base->FindLumpInLevel("SIDEDEFS");
339
base->CacheLump(lump);
340
count = lump->length / sizeof(raw_sidedef_t);
343
if (!lump || count == 0)
344
FatalError("Couldn't find any Sidedefs");
347
PrintDebug("GetSidedefs: num = %d\n", count);
350
lev_sidedefs.Allocate(count);
352
raw_sidedef_t *raw = (raw_sidedef_t *) lump->data;
354
for (int i = 0; i < count; i++, raw++)
356
lev_sidedefs.Set(i, new sidedef_c(i, raw));
360
static sidedef_c *SafeLookupSidedef(uint16_g num)
365
if ((int)num >= lev_sidedefs.num && (sint16_g)(num) < 0)
368
return lev_sidedefs.Get(num);
371
linedef_c::linedef_c(int _idx, const raw_linedef_t *raw)
375
start = lev_vertices.Get(UINT16(raw->start));
376
end = lev_vertices.Get(UINT16(raw->end));
378
/* check for zero-length line */
379
zero_len = (fabs(start->x - end->x) < DIST_EPSILON) &&
380
(fabs(start->y - end->y) < DIST_EPSILON);
382
flags = UINT16(raw->flags);
383
type = UINT16(raw->type);
384
tag = SINT16(raw->tag);
386
two_sided = (flags & LINEFLAG_TWO_SIDED) ? true : false;
388
right = SafeLookupSidedef(UINT16(raw->sidedef1));
389
left = SafeLookupSidedef(UINT16(raw->sidedef2));
392
linedef_c::linedef_c(int _idx, const raw_hexen_linedef_t *raw)
396
start = lev_vertices.Get(UINT16(raw->start));
397
end = lev_vertices.Get(UINT16(raw->end));
399
// check for zero-length line
400
zero_len = (fabs(start->x - end->x) < DIST_EPSILON) &&
401
(fabs(start->y - end->y) < DIST_EPSILON);
403
flags = UINT16(raw->flags);
404
type = UINT8(raw->type);
408
for (int j = 0; j < 5; j++)
409
specials[j] = UINT8(raw->specials[j]);
411
// -JL- Added missing twosided flag handling that caused a broken reject
412
two_sided = (flags & LINEFLAG_TWO_SIDED) ? true : false;
414
right = SafeLookupSidedef(UINT16(raw->sidedef1));
415
left = SafeLookupSidedef(UINT16(raw->sidedef2));
418
linedef_c::~linedef_c()
425
void GetLinedefs(wad_c *base)
429
GetLinedefsHexen(base);
434
lump_c *lump = base->FindLumpInLevel("LINEDEFS");
438
base->CacheLump(lump);
439
count = lump->length / sizeof(raw_linedef_t);
442
if (!lump || count == 0)
443
FatalError("Couldn't find any Linedefs");
446
PrintDebug("GetLinedefs: num = %d\n", count);
449
lev_linedefs.Allocate(count);
451
raw_linedef_t *raw = (raw_linedef_t *) lump->data;
453
for (int i = 0; i < count; i++, raw++)
455
lev_linedefs.Set(i, new linedef_c(i, raw));
462
void GetLinedefsHexen(wad_c *base)
465
lump_c *lump = base->FindLumpInLevel("LINEDEFS");
469
base->CacheLump(lump);
470
count = lump->length / sizeof(raw_hexen_linedef_t);
473
if (!lump || count == 0)
474
FatalError("Couldn't find any Linedefs");
477
PrintDebug("GetLinedefsHexen: num = %d\n", count);
480
lev_linedefs.Allocate(count);
482
raw_hexen_linedef_t *raw = (raw_hexen_linedef_t *) lump->data;
484
for (int i = 0; i < count; i++, raw++)
486
lev_linedefs.Set(i, new linedef_c(i, raw));
490
static vertex_c *FindVertex16(uint16_g index)
493
return lev_gl_verts.Get(index & 0x7FFF);
495
return lev_vertices.Get(index);
498
static vertex_c *FindVertex32(int index)
500
if (index & IS_GL_VERTEX)
501
return lev_gl_verts.Get(index & ~IS_GL_VERTEX);
503
return lev_vertices.Get(index);
506
seg_c::seg_c(int _idx, const raw_gl_seg_t *raw)
512
/// fprintf(stderr, "SEG %d V %d..%d line %d side %d\n",
513
/// index, UINT16(raw->start), UINT16(raw->end), SINT16(raw->linedef), SINT16(raw->side));
515
start = FindVertex16(UINT16(raw->start));
516
end = FindVertex16(UINT16(raw->end));
518
linedef = (SINT16(raw->linedef) == -1) ? NULL :
519
lev_linedefs.Get(UINT16(raw->linedef));
521
side = UINT16(raw->side);
523
sidedef_c *sss = NULL;
526
sss = side ? linedef->left : linedef->right;
528
sector = sss ? sss->sector : NULL;
530
// partner is currently ignored
535
seg_c::seg_c(int _idx, const raw_v3_seg_t *raw)
541
start = FindVertex32(UINT32(raw->start));
542
end = FindVertex32(UINT32(raw->end));
544
linedef = (SINT16(raw->linedef) == -1) ? NULL :
545
lev_linedefs.Get(UINT16(raw->linedef));
547
side = UINT16(raw->flags) & V3SEG_F_LEFT;
549
sidedef_c *sss = NULL;
552
sss = side ? linedef->left : linedef->right;
554
sector = sss ? sss->sector : NULL;
556
// partner is currently ignored
565
void seg_c::precompute_data()
576
p_length = UtilComputeDist(pdx, pdy);
577
p_angle = UtilComputeAngle(pdx, pdy);
579
/// fprintf(stderr, "| (%1.0f,%1.0f)->(%1.0f,%1.0f) Delta (%1.6f, %1.6f)\n",
580
/// psx, psy, pex, pey, pdx, pdy);
583
PrintWarn("Seg %d has zero p_length.\n", index);
585
p_perp = psy * pdx - psx * pdy;
586
p_para = -psx * pdx - psy * pdy;
592
void GetV3Segs(const uint8_g *data, int length)
594
int count = length / sizeof(raw_v3_seg_t);
596
lev_segs.Allocate(count);
598
raw_v3_seg_t *raw = (raw_v3_seg_t *) data;
600
for (int i = 0; i < count; i++, raw++)
602
lev_segs.Set(i, new seg_c(i, raw));
609
void GetGLSegs(wad_c *base)
611
lump_c *lump = base->FindLumpInLevel("GL_SEGS");
614
PrintDebug("GetVertices: num = %d\n", count);
618
FatalError("Couldn't find any GL Segs");
620
base->CacheLump(lump);
622
if (lump->length >= 4 && memcmp(lump->data, lev_v3_magic, 4) == 0)
624
GetV3Segs((uint8_g *)lump->data + 4, lump->length - 4);
628
int count = lump->length / sizeof(raw_gl_seg_t);
630
lev_segs.Allocate(count);
632
raw_gl_seg_t *raw = (raw_gl_seg_t *) lump->data;
634
for (int i = 0; i < count; i++, raw++)
636
lev_segs.Set(i, new seg_c(i, raw));
641
subsec_c::subsec_c(int _idx, const raw_subsec_t *raw)
645
seg_count = UINT16(raw->num);
646
int first = UINT16(raw->first);
648
build_seg_list(first, seg_count);
651
subsec_c::subsec_c(int _idx, const raw_v3_subsec_t *raw)
655
seg_count = UINT32(raw->num);
656
int first = UINT32(raw->first);
658
build_seg_list(first, seg_count);
661
subsec_c::~subsec_c()
665
void subsec_c::append_seg(seg_c *cur)
668
InternalError("Missing seg for subsector !\n");
670
mid_x += (cur->start->x + cur->end->x) / 2.0;
671
mid_y += (cur->start->y + cur->end->y) / 2.0;
673
// add it to the tail
681
seg_c *tail = seg_list;
689
void subsec_c::build_seg_list(int first, int count)
696
for (; count > 0; first++, count--)
698
seg_c *seg = lev_segs.Get(first);
710
void GetV3Subsecs(const uint8_g *data, int length)
712
int count = length / sizeof(raw_v3_subsec_t);
714
lev_subsecs.Allocate(count);
716
raw_v3_subsec_t *raw = (raw_v3_subsec_t *) data;
718
for (int i = 0; i < count; i++, raw++)
720
lev_subsecs.Set(i, new subsec_c(i, raw));
727
void GetGLSubsecs(wad_c *base)
729
lump_c *lump = base->FindLumpInLevel("GL_SSECT");
732
PrintDebug("GetVertices: num = %d\n", count);
736
FatalError("Couldn't find any GL Subsectors");
738
base->CacheLump(lump);
740
if (lump->length >= 4 && memcmp(lump->data, lev_v3_magic, 4) == 0)
742
GetV3Subsecs((uint8_g *)lump->data + 4, lump->length - 4);
746
int count = lump->length / sizeof(raw_subsec_t);
748
lev_subsecs.Allocate(count);
750
raw_subsec_t *raw = (raw_subsec_t *) lump->data;
752
for (int i = 0; i < count; i++, raw++)
754
lev_subsecs.Set(i, new subsec_c(i, raw));
758
void bbox_t::from_raw(const raw_bbox_t *raw)
760
minx = SINT16(raw->minx);
761
miny = SINT16(raw->miny);
762
maxx = SINT16(raw->maxx);
763
maxy = SINT16(raw->maxy);
766
node_c::node_c(int _idx, const raw_node_t *raw)
772
dx = SINT16(raw->dx);
773
dy = SINT16(raw->dy);
775
r.bounds.from_raw(&raw->b1);
776
l.bounds.from_raw(&raw->b2);
778
r.node = l.node = NULL;
779
r.subsec = l.subsec = NULL;
781
int r_idx = UINT16(raw->right);
782
int l_idx = UINT16(raw->left);
785
r.subsec = lev_subsecs.Get(r_idx & 0x7FFF);
787
r.node = lev_nodes.Get(r_idx);
790
l.subsec = lev_subsecs.Get(l_idx & 0x7FFF);
792
l.node = lev_nodes.Get(l_idx);
802
void GetGLNodes(wad_c *base)
805
lump_c *lump = base->FindLumpInLevel("GL_NODES");
809
base->CacheLump(lump);
810
count = lump->length / sizeof(raw_node_t);
813
if (!lump || count < 1)
817
PrintDebug("GetStaleNodes: num = %d\n", count);
820
lev_nodes.Allocate(count);
822
raw_node_t *raw = (raw_node_t *) lump->data;
824
for (int i = 0; i < count; i++, raw++)
826
lev_nodes.Set(i, new node_c(i, raw));
832
/* ----- whole-level routines --------------------------- */
837
void LoadLevel(const char *level_name)
839
// ---- Normal stuff ----
841
if (! the_wad->FindLevel(level_name))
842
FatalError("Unable to find level: %s\n", level_name);
844
// -JL- Identify Hexen mode by presence of BEHAVIOR lump
845
lev_doing_hexen = (the_wad->FindLumpInLevel("BEHAVIOR") != NULL);
847
GetVertices(the_wad);
849
GetSidedefs(the_wad);
850
GetLinedefs(the_wad);
853
// ---- GL stuff ----
857
sprintf(gl_name, "GL_%s", the_wad->current_level->name);
859
wad_c *gl_wad = the_wad;
861
if (! gl_wad->FindLevel(gl_name))
865
if (! gl_wad || ! gl_wad->FindLevel(gl_name))
866
FatalError("Unable to find GL info (%s lump)\n", gl_name);
871
GetGLSubsecs(gl_wad);
874
/// PrintMsg("Loaded %d vertices, %d sectors, %d sides, %d lines, %d things\n",
875
/// num_vertices, num_sectors, num_sidedefs, num_linedefs, num_things);
884
lev_vertices.FreeAll();
885
lev_gl_verts.FreeAll();
886
lev_linedefs.FreeAll();
887
lev_sidedefs.FreeAll();
888
lev_sectors.FreeAll();
889
lev_things.FreeAll();
891
lev_subsecs.FreeAll();
898
void LevelGetBounds(double *lx, double *ly, double *hx, double *hy)
900
node_c *root = lev_nodes.Get(lev_nodes.num - 1);
902
*lx = MIN(root->l.bounds.minx, root->r.bounds.minx);
903
*ly = MIN(root->l.bounds.miny, root->r.bounds.miny);
904
*hx = MAX(root->l.bounds.maxx, root->r.bounds.maxx);
905
*hy = MAX(root->l.bounds.maxy, root->r.bounds.maxy);