/
linedef.h
648 lines (536 loc) · 19.4 KB
/
linedef.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
/** @file linedef.h Map LineDef.
*
* @authors Copyright © 2003-2013 Jaakko Keränen <jaakko.keranen@iki.fi>
* @authors Copyright © 2006-2013 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/
#ifndef LIBDENG_MAP_LINEDEF
#define LIBDENG_MAP_LINEDEF
#include <de/binangle.h>
#include <de/mathutil.h> // Divline
#include <de/Error>
#include "resource/r_data.h"
#include "map/vertex.h"
#include "p_mapdata.h"
#include "p_dmu.h"
#include "MapElement"
class Sector;
class SideDef;
class HEdge;
// Internal flags:
#define LF_POLYOBJ 0x1 ///< Line is part of a polyobject.
#define LF_BSPWINDOW 0x2 ///< Line produced a BSP window. @todo Refactor away.
// Logical face identifiers:
/// @addtogroup map
///@{
#define FRONT 0
#define BACK 1
///@}
// Logical edge identifiers:
/// @addtogroup map
///@{
#define FROM 0
#define TO 1
/// Aliases:
#define START FROM
#define END TO
///@}
/**
* @defgroup sideSectionFlags Side Section Flags
* @ingroup map
*/
///@{
#define SSF_MIDDLE 0x1
#define SSF_BOTTOM 0x2
#define SSF_TOP 0x4
///@}
/**
* Map line.
*
* Despite sharing it's name with a map element present in the id Tech 1 map
* format, this component has a notably different design and slightly different
* purpose in the Doomsday Engine.
*
* Lines always have two logical sides, however they may not have a sector
* attributed to either or both sides.
*
* @note Lines are @em not considered to define the geometry of a map. Instead
* a line should be thought of as a finite line segment in the plane, according
* to the standard definition of a line as used with an arrangement of lines in
* computational geometry.
*
* @see http://en.wikipedia.org/wiki/Arrangement_of_lines
*
* @ingroup map
*
* @todo Should be renamed "Line" (this is not a definition, it @em is a line).
*/
class LineDef : public de::MapElement
{
public:
/// Required sector attribution is missing. @ingroup errors
DENG2_ERROR(MissingSectorError);
/// Required sidedef attribution is missing. @ingroup errors
DENG2_ERROR(MissingSideDefError);
/// The referenced property does not exist. @ingroup errors
DENG2_ERROR(UnknownPropertyError);
/// The referenced property is not writeable. @ingroup errors
DENG2_ERROR(WritePropertyError);
/**
* Logical side of which there are always two (a front and a back).
*/
struct Side
{
public: /// @todo make private:
/// Sector on this side.
Sector *_sector;
/// SideDef on this side.
SideDef *_sideDef;
/// Left-most HEdge on this side.
HEdge *_leftHEdge;
/// Right-most HEdge on this side.
HEdge *_rightHEdge;
/// Framecount of last time shadows were drawn on this side.
int _shadowVisCount;
public:
/**
* Returns @c true iff a Sector is attributed to the side.
*/
bool hasSector() const;
/**
* Returns the Sector attributed to the side.
*
* @see hasSector()
*/
Sector §or() const;
/**
* Returns a pointer to the Sector attributed to the side; otherwise @c 0.
*
* @see hasSector()
*/
inline Sector *sectorPtr() const { return hasSector()? §or() : 0; }
/**
* Returns @c true iff a Sector is attributed to the side.
*/
bool hasSideDef() const;
/**
* Returns the SideDef attributed to the side.
*
* @see hasSideDef()
*/
SideDef &sideDef() const;
/**
* Returns a pointer to the SideDef attributed to the side; otherwise @c 0.
*
* @see hasSideDef()
*/
inline SideDef *sideDefPtr() const { return hasSideDef()? &sideDef() : 0; }
/**
* Returns the left-moset HEdge for the side.
*/
HEdge &leftHEdge() const;
/**
* Returns the right-most HEdge for the side.
*/
HEdge &rightHEdge() const;
/**
* Returns the frame number of the last time shadows linked to the side
* were drawn.
*/
int shadowVisCount() const;
};
public: /// @todo make private:
/// Vertexes [From, To]
Vertex *_v[2];
/// Links to vertex line owner nodes [From, To].
LineOwner *_vo[2];
/// Logical sides [Front, Back]
Side _sides[2];
/// Public DDLF_* flags.
int flags;
/// Internal LF_* flags.
byte inFlags;
/// Logical slope type.
slopetype_t slopeType;
int validCount;
/// Calculated from front side's normal.
binangle_t angle;
coord_t direction[2];
/// Accurate length.
coord_t length;
AABoxd aaBox;
/// Whether the line has been mapped by each player yet.
boolean mapped[DDMAXPLAYERS];
/// Original index in the archived map.
int origIndex;
public:
LineDef();
~LineDef();
/**
* Returns the specified logical side of the line.
*
* @param back If not @c 0 return the Back side; otherwise the Front side.
*/
Side &side(int back);
/// @copydoc side()
Side const &side(int back) const;
/**
* Returns the logical Front side of the line.
*/
inline Side &front() { return side(FRONT); }
/// @copydoc front()
inline Side const &front() const { return side(FRONT); }
/**
* Returns the logical Back side of the line.
*/
inline Side &back() { return side(BACK); }
/// @copydoc back()
inline Side const &back() const { return side(BACK); }
/**
* Returns @c true iff a sector is attributed to the specified side of the line.
*
* @param back If not @c 0 test the Back side; otherwise the Front side.
*/
inline bool hasSector(int back) const { return side(back).hasSector(); }
/**
* Returns @c true iff a sector is attributed to the Front side of the line.
*/
inline bool hasFrontSector() const { return hasSector(FRONT); }
/**
* Returns @c true iff a sector is attributed to the Back side of the line.
*/
inline bool hasBackSector() const { return hasSector(BACK); }
/**
* Returns @c true iff a sidedef is attributed to the specified side of the line.
*
* @param back If not @c 0 test the Back side; otherwise the Front side.
*/
inline bool hasSideDef(int back) const { return side(back).hasSideDef(); }
/**
* Returns @c true iff a sidedef is attributed to the Front side of the line.
*/
inline bool hasFrontSideDef() const { return hasSideDef(FRONT); }
/**
* Returns @c true iff a sidedef is attributed to the Back side of the line.
*/
inline bool hasBackSideDef() const { return hasSideDef(BACK); }
/**
* Convenient accessor method for returning the sector attributed to the
* specified side of the line.
*
* @param back If not @c 0 return the sector for the Back side; otherwise
* the sector of the Front side.
*/
inline Sector §or(int back) { return side(back).sector(); }
/// @copydoc sector()
inline Sector const §or(int back) const { return side(back).sector(); }
/**
* Convenient accessor method for returning a pointer to the sector attributed
* to the specified side of the line.
*
* @param back If not @c 0 return the sector for the Back side; otherwise
* the sector of the Front side.
*/
inline Sector *sectorPtr(int back) { return side(back).sectorPtr(); }
/// @copydoc sector()
inline Sector const *sectorPtr(int back) const { return side(back).sectorPtr(); }
/**
* Returns the sector attributed to the Front side of the line.
*/
inline Sector &frontSector() { return sector(FRONT); }
/// @copydoc backSector()
inline Sector const &frontSector() const { return sector(FRONT); }
/**
* Returns the sector attributed to the Back side of the line.
*/
inline Sector &backSector() { return sector(BACK); }
/// @copydoc backSector()
inline Sector const &backSector() const { return sector(BACK); }
/**
* Convenient accessor method for returning a pointer to the sector attributed
* to the front side of the line.
*/
inline Sector *frontSectorPtr() { return sectorPtr(FRONT); }
/// @copydoc frontSectorPtr()
inline Sector const *frontSectorPtr() const { return sectorPtr(FRONT); }
/**
* Convenient accessor method for returning a pointer to the sector attributed
* to the back side of the line.
*/
inline Sector *backSectorPtr() { return sectorPtr(BACK); }
/// @copydoc frontSectorPtr()
inline Sector const *backSectorPtr() const { return sectorPtr(BACK); }
/**
* Convenient accessor method for returning the sidedef attributed to the
* specified side of the line.
*
* @param back If not @c 0 return the sidedef for the Back side; otherwise
* the sidedef of the Front side.
*/
inline SideDef &sideDef(int back) { return side(back).sideDef(); }
/// @copydoc sideDef()
inline SideDef const &sideDef(int back) const { return side(back).sideDef(); }
/**
* Convenient accessor method for returning a pointer to the sidedef attributed
* to the specified side of the line.
*
* @param back If not @c 0 return the sidedef for the Back side; otherwise
* the sidedef of the Front side.
*/
inline SideDef *sideDefPtr(int back) { return side(back).sideDefPtr(); }
/// @copydoc sideDef()
inline SideDef const *sideDefPtr(int back) const { return side(back).sideDefPtr(); }
/**
* Returns the sidedef attributed to the Front side of the line.
*/
inline SideDef &frontSideDef() { return sideDef(FRONT); }
/// @copydoc backSideDef()
inline SideDef const &frontSideDef() const { return sideDef(FRONT); }
/**
* Returns the sidedef attributed to the Back side of the line.
*/
inline SideDef &backSideDef() { return sideDef(BACK); }
/// @copydoc backSideDef()
inline SideDef const &backSideDef() const { return sideDef(BACK); }
/**
* Convenient accessor method for returning a pointer to the sidedef attributed
* to the front side of the line.
*/
inline SideDef *frontSideDefPtr() { return sideDefPtr(FRONT); }
/// @copydoc frontSideDefPtr()
inline SideDef const *frontSideDefPtr() const { return sideDefPtr(FRONT); }
/**
* Convenient accessor method for returning a pointer to the sidedef attributed
* to the back side of the line.
*/
inline SideDef *backSideDefPtr() { return sideDefPtr(BACK); }
/// @copydoc frontSideDefPtr()
inline SideDef const *backSideDefPtr() const { return sideDefPtr(BACK); }
/**
* Returns @c true iff the line is considered @em self-referencing.
* In this context, self-referencing (a term whose origins stem from the
* DOOM modding community) means a two-sided line (which is to say that
* a Sector is attributed to both logical sides of the line) where the
* attributed sectors for each logical side are the same.
*/
inline bool isSelfReferencing() const
{
return hasFrontSideDef() && hasBackSideDef() && frontSectorPtr() == backSectorPtr();
}
/**
* Returns the specified edge vertex for the line.
*
* @param to If not @c 0 return the To vertex; otherwise the From vertex.
*/
Vertex &vertex(int to);
/// @copydoc vertex()
Vertex const &vertex(int to) const;
/**
* Convenient accessor method for returning the origin of the specified
* edge vertex for the line.
*
* @see vertex()
*/
inline const_pvec2d_t &vertexOrigin(int to) const
{
return vertex(to).origin();
}
/**
* Returns a pointer to the line owner node for the specified edge vertex
* of the line.
*
* @param to If not @c 0 return the owner for the To vertex; otherwise the
* From vertex.
*/
LineOwner *vertexOwner(int to) const;
/**
* Returns the From/Start vertex for the line.
*/
inline Vertex &v1() { return vertex(FROM); }
/// @copydoc v1()
inline Vertex const &v1() const { return vertex(FROM); }
/// @copydoc v1()
/// An alias of v1().
inline Vertex &from() { return v1(); }
/// @copydoc from()
/// An alias of v1().
inline Vertex const &from() const { return v1(); }
/**
* Convenient accessor method for returning the origin of the From/Start
* vertex for the line.
*
* @see v1()
*/
inline const_pvec2d_t &v1Origin() const { return v1().origin(); }
/// @copydoc v1Origin()
/// An alias of v1Origin()
inline const_pvec2d_t &fromOrigin() const { return v1Origin(); }
/**
* Returns a pointer to the line owner node for the From/Start vertex of the line.
*/
inline LineOwner *v1Owner() const { return vertexOwner(FROM); }
/**
* Returns the To/End vertex for the line.
*/
inline Vertex &v2() { return vertex(TO); }
/// @copydoc v2()
inline Vertex const &v2() const { return vertex(TO); }
/// @copydoc v2()
/// An alias of v2().
inline Vertex &to() { return v2(); }
/// @copydoc to()
/// An alias of v2().
inline Vertex const &to() const { return v2(); }
/**
* Convenient accessor method for returning the origin of the To/End
* vertex for the line.
*
* @see v2()
*/
inline const_pvec2d_t &v2Origin() const { return v2().origin(); }
/// @copydoc v2Origin()
/// An alias of v2Origin()
inline const_pvec2d_t &toOrigin() const { return v2Origin(); }
/**
* Returns a pointer to the line owner node for the To/End vertex of the line.
*/
inline LineOwner *v2Owner() const { return vertexOwner(FROM); }
/**
* On which side of the line does the specified box lie?
*
* @param box Bounding box to test.
*
* @return One of the following:
* - Negative: @a box is entirely on the left side.
* - Zero: @a box intersects the line.
* - Positive: @a box is entirely on the right side.
*/
int boxOnSide(AABoxd const &box) const;
/**
* On which side of the line does the specified box lie? The test is
* carried out using fixed-point math for behavior compatible with
* vanilla DOOM. Note that this means there is a maximum size for both
* the bounding box and the line: neither can exceed the fixed-point
* 16.16 range (about 65k units).
*
* @param box Bounding box to test.
*
* @return One of the following:
* - Negative: @a box is entirely on the left side.
* - Zero: @a box intersects the line.
* - Positive: @a box is entirely on the right side.
*/
int boxOnSide_FixedPrecision(AABoxd const &box) const;
/**
* @param offset Returns the position of the nearest point along the line [0..1].
*/
coord_t pointDistance(const_pvec2d_t point, coord_t *offset) const;
inline coord_t pointDistance(coord_t x, coord_t y, coord_t *offset) const
{
coord_t point[2] = { x, y };
return pointDistance(point, offset);
}
/**
* On which side of the line does the specified point lie?
*
* @param point Point in the map coordinate space to test.
*
* @return One of the following:
* - Negative: @a point is to the left/back side.
* - Zero: @a point lies directly on the line.
* - Positive: @a point is to the right/front side.
*/
coord_t pointOnSide(const_pvec2d_t point) const;
inline coord_t pointOnSide(coord_t x, coord_t y) const
{
coord_t point[2] = { x, y };
return pointOnSide(point);
}
/**
* Configure the specified divline_t by setting the origin point to the
* line's left (i.e., first) vertex and the direction vector parallel to
* the line's direction vector.
*
* @param divline divline_t instance to be configured.
*/
void configureDivline(divline_t &divline) const;
/**
* Find the "sharp" Z coordinate range of the opening on @a side. The
* open range is defined as the gap between foor and ceiling on @a side
* clipped by the floor and ceiling planes on the back side (if present).
*
* @param bottom Bottom Z height is written here. Can be @c NULL.
* @param top Top Z height is written here. Can be @c NULL.
*
* @return Height of the open range.
*/
coord_t openRange(int side, coord_t *bottom, coord_t *top) const;
/// Same as openRange() but works with the "visual" (i.e., smoothed)
/// plane height coordinates rather than the "sharp" coordinates.
coord_t visOpenRange(int side, coord_t *bottom, coord_t *top) const;
/**
* Configure the specified TraceOpening according to the opening defined
* by the inner-minimal plane heights which intercept the line.
*
* @param opening TraceOpening instance to be configured.
*/
void configureTraceOpening(TraceOpening &opening) const;
/**
* Calculate a unit vector parallel to the line.
*
* @todo No longer needed (SideDef stores tangent space normals).
*
* @param unitVector Unit vector is written here.
*/
void unitVector(pvec2f_t unitVec) const;
/**
* Update the line's slopetype and map space angle delta according to
* the points defined by it's vertices.
*/
void updateSlope();
/**
* Update the line's map space axis-aligned bounding box to encompass
* the points defined by it's vertices.
*/
void updateAABox();
/**
* The DOOM lighting model applies a sector light level delta when drawing
* line segments based on their 2D world angle.
*
* @param side Side of the line we are interested in.
* @param deltaL Light delta for the left edge written here. Can be @c NULL.
* @param deltaR Light delta for the right edge written here. Can be @c NULL.
*
* @deprecated Now that we store surface tangent space normals use those
* rather than angles. @todo Remove me.
*/
void lightLevelDelta(int side, float *deltaL, float *deltaR) const;
/**
* Get a property value, selected by DMU_* name.
*
* @param args Property arguments.
* @return Always @c 0 (can be used as an iterator).
*/
int property(setargs_t &args) const;
/**
* Update a property value, selected by DMU_* name.
*
* @param args Property arguments.
* @return Always @c 0 (can be used as an iterator).
*/
int setProperty(setargs_t const &args);
};
#endif // LIBDENG_MAP_LINEDEF