This repository was archived by the owner on Mar 19, 2025. It is now read-only.
forked from Phobos-developers/YRpp
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDir.h
142 lines (115 loc) · 3.29 KB
/
Dir.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
#pragma once
// Please update this file with STL library <bit>!
enum class DirType : unsigned char;
// North -> 0x0000
// South -> 0x8000
// ...
// Just a very simple BAM
struct DirStruct
{
public:
explicit DirStruct() noexcept : Raw { 0 } { }
explicit DirStruct(int raw) noexcept : Raw { static_cast<unsigned short>(raw) } { }
explicit DirStruct(double rad) noexcept { SetRadian<65536>(rad); }
explicit DirStruct(const DirType dir) noexcept { SetDir(dir); }
explicit DirStruct(const noinit_t& noinit) noexcept { }
bool operator==(const DirStruct& another) const
{
return Raw == another.Raw;
}
bool operator!=(const DirStruct& another) const
{
return Raw != another.Raw;
}
void SetDir(DirType dir)
{
Raw = static_cast<unsigned short>(static_cast<unsigned char>(dir) * 256);
}
DirType GetDir() const
{
return static_cast<DirType>(Raw / 256);
}
// If you want to divide it into 32 facings, as 32 has 5 bits
// then you should type <5> here.
// So does the others.
template<size_t Bits>
constexpr size_t GetValue(size_t offset = 0) const
{
return TranslateFixedPoint<16, Bits>(Raw, offset);
}
template<size_t Bits>
constexpr void SetValue(size_t value, size_t offset = 0)
{
Raw = static_cast<unsigned short>(TranslateFixedPoint<Bits, 16>(value, offset));
}
template<size_t Count>
constexpr size_t GetFacing(size_t offset = 0) const
{
static_assert(HasSingleBit(Count));
constexpr size_t Bits = BitWidth<Count - 1>();
return GetValue<Bits>(offset);
}
template<size_t Count>
constexpr void SetFacing(size_t value, size_t offset = 0)
{
static_assert(HasSingleBit(Count));
constexpr size_t Bits = BitWidth<Count - 1>();
SetValue<Bits>(value, offset);
}
template<size_t FacingCount>
double GetRadian()
{
static_assert(HasSingleBit(FacingCount));
constexpr size_t Bits = BitWidth<FacingCount - 1>();
constexpr size_t Max = (1 << Bits) - 1;
size_t value = GetValue<Bits>();
int dir = static_cast<int>(value) - FacingCount / 4; // LRotate 90 degrees
return dir * (-Math::TwoPi / FacingCount);
}
template<size_t FacingCount>
void SetRadian(double rad)
{
static_assert(HasSingleBit(FacingCount));
constexpr size_t Bits = BitWidth<FacingCount - 1>();
constexpr size_t Max = (1 << Bits) - 1;
int dir = static_cast<int>(rad / (-Math::TwoPi / FacingCount));
size_t value = dir + FacingCount / 4; // RRotate 90 degrees
SetValue<Bits>(value & Max);
}
private:
constexpr static bool HasSingleBit(size_t x) noexcept
{
return x != 0 && (x & (x - 1)) == 0;
}
template<size_t X>
constexpr static size_t BitWidth() noexcept
{
if constexpr (X == 0)
return 0;
size_t T = X;
size_t cnt = 0;
while (T)
{
T >>= 1;
++cnt;
}
return cnt;
}
template<size_t BitsFrom, size_t BitsTo>
constexpr static size_t TranslateFixedPoint(size_t value, size_t offset = 0)
{
constexpr size_t MaskIn = ((1u << BitsFrom) - 1);
constexpr size_t MaskOut = ((1u << BitsTo) - 1);
if constexpr (BitsFrom > BitsTo)
return (((((value & MaskIn) >> (BitsFrom - BitsTo - 1)) + 1) >> 1) + offset) & MaskOut;
else if constexpr (BitsFrom < BitsTo)
return (((value - offset) & MaskIn) << (BitsTo - BitsFrom)) & MaskOut;
else
return value & MaskOut;
}
public:
unsigned short Raw;
private:
unsigned short Padding;
};
static_assert(sizeof(DirStruct) == 4);