summaryrefslogtreecommitdiff
path: root/src/engine/CoreMath.h
blob: b3dd2753b3cca56f62d3169363cce15d35fc93e9 (plain)
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
#ifndef CORE_MATH_H
#define CORE_MATH_H

#ifdef __cplusplus
#include <nlohmann/json.hpp>
#endif

#include <libultraship.h>

/**
 * @file CoreMath.h
 * 
 * Basic vector structs for manipulating 2D and 3D coordinates
 * 
 */

struct RGBA8 {
    uint8_t r, g, b, a;
#ifdef __cplusplus
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(RGBA8, r, g, b, a)
#endif
};


/**
 * 
 * Applies pos, rot, and scale
 *
 */
struct FVector {
    float x, y, z;

#ifdef __cplusplus
    // Operator to add two FVector objects
    FVector operator+(const FVector& other) const {
        return FVector(x + other.x, y + other.y, z + other.z);
    }

    // Operator to subtract two FVector objects
    FVector operator-(const FVector& other) const {
        return FVector(x - other.x, y - other.y, z - other.z);
    }

    // Operator to multiply a FVector by a scalar (float)
    FVector operator*(float scalar) const {
        return FVector(x * scalar, y * scalar, z * scalar);
    }

    float Dot(const FVector& other) const {
        return x * other.x + y * other.y + z * other.z;
    }


    FVector Cross(const FVector& other) const {
        return FVector(
            y * other.z - z * other.y,
            z * other.x - x * other.z,
            x * other.y - y * other.x
        );
    }

    float Magnitude() const {
        return std::sqrt(x * x + y * y + z * z);
    }

    FVector Normalize() const {
        float len = std::sqrt(x * x + y * y + z * z);
        if (len > 0.0001f) {
            return FVector(
                x / len, y / len, z / len
            );
        }
        return FVector(0, 0, 0);
    }

    float Square() const {
        return x * x + y * y + z * z;
    }

    FVector() : x(0), y(0), z(0) {}
    FVector(float x, float y, float z) : x(x), y(y), z(z) {}
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(FVector, x, y, z)
#endif // __cplusplus
};

struct FVector4 {
    float x, y, z, w;

#ifdef __cplusplus

    FVector4() : x(0), y(0), z(0), w(0) {}
    FVector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
#endif // __cplusplus
};

/**
 * For providing X and Z when you do not need Y
 * Some actors set themselves on the surface automatically
 * which means it does not use a Y coordinate
 * The train follows a set Y value. The hedgehog's patrolPoint only uses X and Z.
 */
struct FVector2D {
    float x, z;

#ifdef __cplusplus
    FVector2D& operator=(const FVector2D& other) {
        x = other.x;
        z = other.z;
        return *this;
    }

    FVector2D() : x(0), z(0) {}
    FVector2D(float x, float z) : x(x), z(z) {}
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(FVector2D, x, z)
#endif // __cplusplus
};

// Sets integer X Z coordinates
typedef struct IVector2D {
    int32_t X, Y;

#ifdef __cplusplus
    IVector2D() : X(0), Y(0) {}  // Default constructor

    IVector2D(int32_t x, int32_t y) : X(x), Y(y) {}  // Constructor to initialize with values


    IVector2D& operator=(const IVector2D& other) {
        X = other.X;
        Y = other.Y;
        return *this;
    }
#endif // __cplusplus
} IVector2D;

/**
 * This struct immediately converts float pitch/yaw/roll in degrees to n64 int16_t binary angles 0-0xFFFF == 0-360 degrees
 * ToDegrees() Receive an FRotator of float degrees back.
 * Set() to update an IRotator using n64 int16_t binary angles 0-0xFFFF (ex. IRotator.Set(0, 0x4000, 0) for Y 90 degrees)
 */
struct IRotator {
    uint16_t pitch, yaw, roll;

#ifdef __cplusplus
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(IRotator, pitch, yaw, roll)

    IRotator& operator=(const IRotator& other) {
        pitch = other.pitch;
        yaw   = other.yaw;
        roll  = other.roll;
        return *this;
    }

    void Set(uint16_t p, uint16_t y, uint16_t r) {
        pitch = p;
        yaw = y;
        roll = r;
    }

    IRotator() : pitch(0), yaw(0), roll(0) {}
    IRotator(float p, float y, float r) {
        pitch = p * (UINT16_MAX / 360);
        yaw   = y * (UINT16_MAX / 360);
        roll  = r * (UINT16_MAX / 360);
    }

    // Convert to radians as FVector
    [[nodiscard]] FVector ToRadians() const {
        float scale = 2.0f * M_PI / 65536.0f;
        return FVector(
            pitch * scale,
            yaw   * scale,
            roll  * scale
        );
    }
#endif // __cplusplus
};

/**
 * Use IRotator unless you want to do some math in degrees.
 * Always use ToBinary() or IRotator when sending into matrices or apply translation functions
 * Convert from IRotator to FRotator float degrees by doing FRotator(myIRotator);
 */
struct FRotator {
    float pitch, yaw, roll;

#ifdef __cplusplus
    FRotator& operator=(const FRotator& other) {
        pitch = other.pitch;
        yaw   = other.yaw;
        roll  = other.roll;
        return *this;
    }

    // Convert to binary rotator 0 --> INT16_MAX
    [[nodiscard]] IRotator ToBinary() const {
        return IRotator(
            static_cast<uint16_t>(pitch * (UINT16_MAX / 360)),
            static_cast<uint16_t>(yaw   * (UINT16_MAX / 360)),
            static_cast<uint16_t>(roll  * (UINT16_MAX / 360))
        );
    }

    FRotator() : pitch(0), yaw(0), roll(0) {}
    FRotator(float p, float y, float r) : pitch(p), yaw(y), roll(r) {}
    FRotator(IRotator rot) {
        pitch = static_cast<float>(rot.pitch * (360 / UINT16_MAX));
        yaw   = static_cast<float>(rot.yaw   * (360 / UINT16_MAX));
        roll  = static_cast<float>(rot.roll  * (360 / UINT16_MAX));
    }
#endif // __cplusplus
};

/**
 * For selecting a section of a track path
 * Usage: IPathSpan(point1, point2) --> IPathSpan(40, 65)
 */
struct IPathSpan {
    int32_t Start, End;

#ifdef __cplusplus
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(IPathSpan, Start, End)
    // Default Constructor
    IPathSpan() : Start(0), End(0) {}

    // Parameterized Constructor
    IPathSpan(int InStart, int InEnd)
        : Start(InStart), End(InEnd) {}

    // Copy Assignment Operator
    IPathSpan& operator=(const IPathSpan& Other) {
        if (this != &Other) { // Avoid self-assignment
            Start = Other.Start;
            End = Other.End;
        }
        return *this;
    }

    // Equality Operator
    bool operator==(const IPathSpan& Other) const {
        return Start == Other.Start && End == Other.End;
    }

    // Inequality Operator
    bool operator!=(const IPathSpan& Other) const {
        return !(*this == Other);
    }
#endif // __cplusplus
};

#endif // CORE_MATH_H