summaryrefslogtreecommitdiff
path: root/include/toBeSorted/d_path.h
blob: 568560085f888f663870fe21d27d158bde70917c (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
#ifndef D_PATH_H
#define D_PATH_H

#include "common.h"
#include "d/d_bzs_types.h"
#include "m/m_vec.h"

/**
 * A dPath_c describes a parametric 3D curve in a stage.
 * This base path class provides read-only evaluation of the curve.
 *
 * A path consists of a number of points that this curve passes through.
 * Paths can have two ends, or wrap around, connecting the end point with the start point again.
 * The curve can either linearly connect the points, or it can be implemented as a spline
 * (splines are used for certain actors where smooth movement is necessary, e.g. Sandship).
 *
 * A curve point (or the segment between that point and the next) is identified by an integer point index [0; n-1], and
 * each segment itself is parametrized by a float parameter in [0.0; 1.0]. We call this parameter "time", though since
 * no requirements are imposed on the distance between points, there is no guarantee of constant speed across the curve.
 * ActorOnRail_Ext (todo rename) provides calculations that allow actors to move along the curve with constant speed.
 */
class dPath_c {
private:
    const PATH *mpPathPtr;
    s32 mRoomIndex;
    bool mPathSubtype;

    /** Must only be called for spline paths. Extracts the relevant path points and control points for the given
     * segment. */
    bool extractControlPoints(
        s32 pointIndex, mVec3_c &currPos, mVec3_c &currControl2, mVec3_c &nextControl1, mVec3_c &nextPos
    ) const;

    /**
     * Check if the given path segment is a linear segment - even splines can have linear segments!
     * This can speed up some calculations.
     */
    bool isLinearSegment(s32 pointIndex) const;

    void set(const PATH *path, s32 roomIndex, bool subtype);

    const PNT *getPathPoint(s32 pointIndex) const;
    const BPNT *getPathBpoint(s32 pointIndex) const;

public:
    dPath_c();

    virtual ~dPath_c();

    bool isWrapping() const {
        return mpPathPtr->flags & PATH_FLAG_WRAP_AROUND;
    }

    bool isLinear() const {
        return (mpPathPtr->flags & PATH_FLAG_SPLINE) == 0;
    }

    s32 getNumPoints() const {
        return mpPathPtr->pointCount;
    }

    bool initWithPathId(s32 pathId, s32 roomId, bool pathSubtype);
    bool initWithPathIndex(s32 pathIndex, s32 roomId, bool pathSubtype);

    void clear();

    /** Get a given point that the curve passes through. */
    const Vec *getPoint(s32 pointIndex) const;
    /** Evaluates the curve position for the given segment and time. */
    void getPoint(s32 pointIndex, f64 time, mVec3_c &out) const;
    /** Extract point param - TODO what is this used for? */
    u8 getPointParam(s32 pointIndex, s32 param) const;

    /** Return the index of this PATH in the current room. */
    u16 getMyPathIndex(s32 roomId) const;
    /** Apparently paths can be linked somehow. */
    bool getNextPath(dPath_c *next) const;

    /**
     * Approximate the time for the given distance along the segment.
     * The return value is clamped to [0.0, 1.0]. If the distance exceeds
     * the length of this segment, write the excess to the provided pointer.
     */
    f32 getSegmentTime(s32 pointIndex, f32 segmentDistance, f32 stepSize, f32 *excess);

    /**
     * Approximates the distance already traveled on the given segment for the given time.
     * Calling this with time == 1.0f returns the segment length.
     * Higher resolution -> higher accuracy.
     */
    f32 getDistanceMovedOnSegment(s32 pointIndex, s32 resolution, f32 time) const;
    /** Calculates the normalized direction of an actor moving along the segment for the given time. */
    bool getDirection(s32 segmentIndex, f32 time, mVec3_c &result) const;
    /** Calculates the speed (scalar) of an actor moving along the segment at the given time. */
    bool getSpeed(s32 segmentIndex, f32 time, f32 *result) const;
    /** Calculates the velocity (vector) of an actor moving along the segment at the given time. */
    bool getVelocity(s32 segmentIndex, f32 time, mVec3_c &result) const;
};

/** A stateful "path driver" that moves along a given path with a given speed. */
class ActorOnRail_Ext {
public:
    ActorOnRail_Ext();
    ~ActorOnRail_Ext();

    f32 getRemainingDistanceOnSegment() const;
    s32 getClosestXZPoint(const mVec3_c &) const;
    void setSegment(s32 segmentIndex, f32 segmentTime);
    bool
    init(s32 pathIndex, s32 roomId, u32 flags, s32 segmentIndex, bool pathSubtype, f32 segmentTime, f32 speed, f32 unk);
    s32 execute();

    s32 getSegmentIndex() const {
        return mSegmentIndex;
    }

    f32 getSegmentTime() const {
        return mSegmentTime;
    }

    bool CheckFlag(u32 flag) const {
        return (mFlags & flag) != 0;
    }

    void ClearFlag(u32 flag) {
        mFlags &= ~flag;
    }

    void SetFlag(u32 flag) {
        mFlags |= flag;
    }

    const mVec3_c &getPosition() const {
        return mPosition;
    }

    void setSpeed(f32 speed) {
        mSpeed = speed;
    }

    void getDirection(mVec3_c &result) {
        mPath.getDirection(mSegmentIndex, mSegmentTime, result);
    }

    bool checkFlag(u32 flags) const {
        return (mFlags & flags) != 0;
    }

    void offFlag(u32 flags) {
        mFlags &= ~flags;
    }

    void onFlag(u32 flags) {
        mFlags |= flags;
    }

private:
    s32 getNextPointIndex(s32 point) const;
    s32 getNextPointIndex() const;

    /* 0x00 */ dPath_c mPath;
    /* 0x10 */ s32 mSegmentIndex;
    /* 0x14 */ f32 mSegmentTime;
    /* 0x18 */ f32 mSpeed;
    /* 0x1C */ u32 mFlags;
    /* 0x20 */ f32 field_0x20;
    /* 0x24 */ f32 mSegmentDistance;
    /* 0x28 */ mVec3_c mPosition;
};

class ActorOnRail3 {
    /* 0x00 */ dPath_c mPath;
    /* 0x10 */ u16 mSomePntIdx;
    /* 0x14 */ u32 mFlags;

public:
    ActorOnRail3() : mSomePntIdx(0), mFlags(0) {}
};

#endif