mirror of
https://github.com/zeldaret/ss
synced 2026-05-23 15:01:38 -04:00
181 lines
5.7 KiB
C++
181 lines
5.7 KiB
C++
#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
|