mirror of
https://github.com/mangosfour/server.git
synced 2025-12-18 19:37:01 +00:00
Various Cleanups (movement/)
This commit is contained in:
parent
6379a746d7
commit
0d2bedadae
13 changed files with 1122 additions and 1113 deletions
|
|
@ -20,297 +20,300 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
namespace Movement{
|
namespace Movement
|
||||||
|
|
||||||
extern float computeFallTime(float path_length, bool isSafeFall);
|
|
||||||
extern float computeFallElevation(float time_passed, bool isSafeFall, float start_velocy);
|
|
||||||
extern float computeFallElevation(float time_passed);
|
|
||||||
|
|
||||||
Location MoveSpline::ComputePosition() const
|
|
||||||
{
|
{
|
||||||
MANGOS_ASSERT(Initialized());
|
|
||||||
|
|
||||||
float u = 1.f;
|
extern float computeFallTime(float path_length, bool isSafeFall);
|
||||||
int32 seg_time = spline.length(point_Idx,point_Idx+1);
|
extern float computeFallElevation(float time_passed, bool isSafeFall, float start_velocy);
|
||||||
if (seg_time > 0)
|
extern float computeFallElevation(float time_passed);
|
||||||
u = (time_passed - spline.length(point_Idx)) / (float)seg_time;
|
|
||||||
Location c;
|
|
||||||
c.orientation = initialOrientation;
|
|
||||||
spline.evaluate_percent(point_Idx, u, c);
|
|
||||||
|
|
||||||
if (splineflags.animation)
|
Location MoveSpline::ComputePosition() const
|
||||||
;// MoveSplineFlag::Animation disables falling or parabolic movement
|
|
||||||
else if (splineflags.parabolic)
|
|
||||||
computeParabolicElevation(c.z);
|
|
||||||
else if (splineflags.falling)
|
|
||||||
computeFallElevation(c.z);
|
|
||||||
|
|
||||||
if (splineflags.done && splineflags.isFacing())
|
|
||||||
{
|
{
|
||||||
if (splineflags.final_angle)
|
MANGOS_ASSERT(Initialized());
|
||||||
c.orientation = facing.angle;
|
|
||||||
else if (splineflags.final_point)
|
float u = 1.f;
|
||||||
c.orientation = atan2(facing.f.y-c.y, facing.f.x-c.x);
|
int32 seg_time = spline.length(point_Idx,point_Idx+1);
|
||||||
//nothing to do for MoveSplineFlag::Final_Target flag
|
if (seg_time > 0)
|
||||||
}
|
u = (time_passed - spline.length(point_Idx)) / (float)seg_time;
|
||||||
else
|
Location c;
|
||||||
{
|
c.orientation = initialOrientation;
|
||||||
if (!splineflags.hasFlag(MoveSplineFlag::OrientationFixed|MoveSplineFlag::Falling))
|
spline.evaluate_percent(point_Idx, u, c);
|
||||||
|
|
||||||
|
if (splineflags.animation)
|
||||||
|
;// MoveSplineFlag::Animation disables falling or parabolic movement
|
||||||
|
else if (splineflags.parabolic)
|
||||||
|
computeParabolicElevation(c.z);
|
||||||
|
else if (splineflags.falling)
|
||||||
|
computeFallElevation(c.z);
|
||||||
|
|
||||||
|
if (splineflags.done && splineflags.isFacing())
|
||||||
{
|
{
|
||||||
Vector3 hermite;
|
if (splineflags.final_angle)
|
||||||
spline.evaluate_derivative(point_Idx,u,hermite);
|
c.orientation = facing.angle;
|
||||||
c.orientation = atan2(hermite.y, hermite.x);
|
else if (splineflags.final_point)
|
||||||
|
c.orientation = atan2(facing.f.y-c.y, facing.f.x-c.x);
|
||||||
|
//nothing to do for MoveSplineFlag::Final_Target flag
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (splineflags.orientationInversed)
|
|
||||||
c.orientation = -c.orientation;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveSpline::computeParabolicElevation(float& el) const
|
|
||||||
{
|
|
||||||
if (time_passed > effect_start_time)
|
|
||||||
{
|
|
||||||
float t_passedf = MSToSec(time_passed - effect_start_time);
|
|
||||||
float t_durationf = MSToSec(Duration() - effect_start_time); //client use not modified duration here
|
|
||||||
|
|
||||||
// -a*x*x + bx + c:
|
|
||||||
//(dur * v3->z_acceleration * dt)/2 - (v3->z_acceleration * dt * dt)/2 + Z;
|
|
||||||
el += (t_durationf - t_passedf) * 0.5f * vertical_acceleration * t_passedf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveSpline::computeFallElevation(float& el) const
|
|
||||||
{
|
|
||||||
float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed));
|
|
||||||
float final_z = FinalDestination().z;
|
|
||||||
if (z_now < final_z)
|
|
||||||
el = final_z;
|
|
||||||
else
|
|
||||||
el = z_now;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32 computeDuration(float length, float velocity)
|
|
||||||
{
|
|
||||||
return SecToMS(length / velocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FallInitializer
|
|
||||||
{
|
|
||||||
FallInitializer(float _start_elevation) : start_elevation(_start_elevation) {}
|
|
||||||
float start_elevation;
|
|
||||||
inline int32 operator()(Spline<int32>& s, int32 i)
|
|
||||||
{
|
|
||||||
return Movement::computeFallTime(start_elevation - s.getPoint(i+1).z,false) * 1000.f;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum{
|
|
||||||
minimal_duration = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CommonInitializer
|
|
||||||
{
|
|
||||||
CommonInitializer(float _velocity) : velocityInv(1000.f/_velocity), time(minimal_duration) {}
|
|
||||||
float velocityInv;
|
|
||||||
int32 time;
|
|
||||||
inline int32 operator()(Spline<int32>& s, int32 i)
|
|
||||||
{
|
|
||||||
time += (s.SegLength(i) * velocityInv);
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void MoveSpline::init_spline(const MoveSplineInitArgs& args)
|
|
||||||
{
|
|
||||||
const SplineBase::EvaluationMode modes[2] = {SplineBase::ModeLinear,SplineBase::ModeCatmullrom};
|
|
||||||
if (args.flags.cyclic)
|
|
||||||
{
|
|
||||||
uint32 cyclic_point = 0;
|
|
||||||
// MoveSplineFlag::Enter_Cycle support dropped
|
|
||||||
//if (splineflags & SPLINEFLAG_ENTER_CYCLE)
|
|
||||||
//cyclic_point = 1; // shouldn't be modified, came from client
|
|
||||||
spline.init_cyclic_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], cyclic_point);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
spline.init_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// init spline timestamps
|
|
||||||
if (splineflags.falling)
|
|
||||||
{
|
|
||||||
FallInitializer init(spline.getPoint(spline.first()).z);
|
|
||||||
spline.initLengths(init);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CommonInitializer init(args.velocity);
|
|
||||||
spline.initLengths(init);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: what to do in such cases? problem is in input data (all points are at same coords)
|
|
||||||
if (spline.length() < minimal_duration)
|
|
||||||
{
|
|
||||||
sLog.outError("MoveSpline::init_spline: zero length spline, wrong input data?");
|
|
||||||
spline.set_length(spline.last(), spline.isCyclic() ? 1000 : 1);
|
|
||||||
}
|
|
||||||
point_Idx = spline.first();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveSpline::Initialize(const MoveSplineInitArgs& args)
|
|
||||||
{
|
|
||||||
splineflags = args.flags;
|
|
||||||
facing = args.facing;
|
|
||||||
m_Id = args.splineId;
|
|
||||||
point_Idx_offset = args.path_Idx_offset;
|
|
||||||
initialOrientation = args.initialOrientation;
|
|
||||||
|
|
||||||
time_passed = 0;
|
|
||||||
vertical_acceleration = 0.f;
|
|
||||||
effect_start_time = 0;
|
|
||||||
|
|
||||||
init_spline(args);
|
|
||||||
|
|
||||||
// init parabolic / animation
|
|
||||||
// spline initialized, duration known and i able to compute parabolic acceleration
|
|
||||||
if (args.flags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation))
|
|
||||||
{
|
|
||||||
effect_start_time = Duration() * args.time_perc;
|
|
||||||
if (args.flags.parabolic && effect_start_time < Duration())
|
|
||||||
{
|
{
|
||||||
float f_duration = MSToSec(Duration() - effect_start_time);
|
if (!splineflags.hasFlag(MoveSplineFlag::OrientationFixed|MoveSplineFlag::Falling))
|
||||||
vertical_acceleration = args.parabolic_amplitude * 8.f / (f_duration * f_duration);
|
{
|
||||||
|
Vector3 hermite;
|
||||||
|
spline.evaluate_derivative(point_Idx,u,hermite);
|
||||||
|
c.orientation = atan2(hermite.y, hermite.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splineflags.orientationInversed)
|
||||||
|
c.orientation = -c.orientation;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveSpline::computeParabolicElevation(float& el) const
|
||||||
|
{
|
||||||
|
if (time_passed > effect_start_time)
|
||||||
|
{
|
||||||
|
float t_passedf = MSToSec(time_passed - effect_start_time);
|
||||||
|
float t_durationf = MSToSec(Duration() - effect_start_time); //client use not modified duration here
|
||||||
|
|
||||||
|
// -a*x*x + bx + c:
|
||||||
|
//(dur * v3->z_acceleration * dt)/2 - (v3->z_acceleration * dt * dt)/2 + Z;
|
||||||
|
el += (t_durationf - t_passedf) * 0.5f * vertical_acceleration * t_passedf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
MoveSpline::MoveSpline() : m_Id(0), time_passed(0),
|
void MoveSpline::computeFallElevation(float& el) const
|
||||||
vertical_acceleration(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0), initialOrientation(0.f)
|
{
|
||||||
{
|
float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed));
|
||||||
splineflags.done = true;
|
float final_z = FinalDestination().z;
|
||||||
}
|
if (z_now < final_z)
|
||||||
|
el = final_z;
|
||||||
|
else
|
||||||
|
el = z_now;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32 computeDuration(float length, float velocity)
|
||||||
|
{
|
||||||
|
return SecToMS(length / velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FallInitializer
|
||||||
|
{
|
||||||
|
FallInitializer(float _start_elevation) : start_elevation(_start_elevation) {}
|
||||||
|
float start_elevation;
|
||||||
|
inline int32 operator()(Spline<int32>& s, int32 i)
|
||||||
|
{
|
||||||
|
return Movement::computeFallTime(start_elevation - s.getPoint(i+1).z,false) * 1000.f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
minimal_duration = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommonInitializer
|
||||||
|
{
|
||||||
|
CommonInitializer(float _velocity) : velocityInv(1000.f/_velocity), time(minimal_duration) {}
|
||||||
|
float velocityInv;
|
||||||
|
int32 time;
|
||||||
|
inline int32 operator()(Spline<int32>& s, int32 i)
|
||||||
|
{
|
||||||
|
time += (s.SegLength(i) * velocityInv);
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void MoveSpline::init_spline(const MoveSplineInitArgs& args)
|
||||||
|
{
|
||||||
|
const SplineBase::EvaluationMode modes[2] = {SplineBase::ModeLinear,SplineBase::ModeCatmullrom};
|
||||||
|
if (args.flags.cyclic)
|
||||||
|
{
|
||||||
|
uint32 cyclic_point = 0;
|
||||||
|
// MoveSplineFlag::Enter_Cycle support dropped
|
||||||
|
//if (splineflags & SPLINEFLAG_ENTER_CYCLE)
|
||||||
|
//cyclic_point = 1; // shouldn't be modified, came from client
|
||||||
|
spline.init_cyclic_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], cyclic_point);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spline.init_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// init spline timestamps
|
||||||
|
if (splineflags.falling)
|
||||||
|
{
|
||||||
|
FallInitializer init(spline.getPoint(spline.first()).z);
|
||||||
|
spline.initLengths(init);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CommonInitializer init(args.velocity);
|
||||||
|
spline.initLengths(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: what to do in such cases? problem is in input data (all points are at same coords)
|
||||||
|
if (spline.length() < minimal_duration)
|
||||||
|
{
|
||||||
|
sLog.outError("MoveSpline::init_spline: zero length spline, wrong input data?");
|
||||||
|
spline.set_length(spline.last(), spline.isCyclic() ? 1000 : 1);
|
||||||
|
}
|
||||||
|
point_Idx = spline.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveSpline::Initialize(const MoveSplineInitArgs& args)
|
||||||
|
{
|
||||||
|
splineflags = args.flags;
|
||||||
|
facing = args.facing;
|
||||||
|
m_Id = args.splineId;
|
||||||
|
point_Idx_offset = args.path_Idx_offset;
|
||||||
|
initialOrientation = args.initialOrientation;
|
||||||
|
|
||||||
|
time_passed = 0;
|
||||||
|
vertical_acceleration = 0.f;
|
||||||
|
effect_start_time = 0;
|
||||||
|
|
||||||
|
init_spline(args);
|
||||||
|
|
||||||
|
// init parabolic / animation
|
||||||
|
// spline initialized, duration known and i able to compute parabolic acceleration
|
||||||
|
if (args.flags & (MoveSplineFlag::Parabolic | MoveSplineFlag::Animation))
|
||||||
|
{
|
||||||
|
effect_start_time = Duration() * args.time_perc;
|
||||||
|
if (args.flags.parabolic && effect_start_time < Duration())
|
||||||
|
{
|
||||||
|
float f_duration = MSToSec(Duration() - effect_start_time);
|
||||||
|
vertical_acceleration = args.parabolic_amplitude * 8.f / (f_duration * f_duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveSpline::MoveSpline() : m_Id(0), time_passed(0),
|
||||||
|
vertical_acceleration(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0), initialOrientation(0.f)
|
||||||
|
{
|
||||||
|
splineflags.done = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// ============================================================================================
|
/// ============================================================================================
|
||||||
|
|
||||||
bool MoveSplineInitArgs::Validate() const
|
bool MoveSplineInitArgs::Validate() const
|
||||||
{
|
{
|
||||||
#define CHECK(exp) \
|
#define CHECK(exp) \
|
||||||
if (!(exp))\
|
if (!(exp))\
|
||||||
{\
|
{\
|
||||||
sLog.outError("MoveSplineInitArgs::Validate: expression '%s' failed", #exp);\
|
sLog.outError("MoveSplineInitArgs::Validate: expression '%s' failed", #exp);\
|
||||||
return false;\
|
return false;\
|
||||||
}
|
}
|
||||||
CHECK(path.size() > 1);
|
CHECK(path.size() > 1);
|
||||||
CHECK(velocity > 0.f);
|
CHECK(velocity > 0.f);
|
||||||
CHECK(time_perc >= 0.f && time_perc <= 1.f);
|
CHECK(time_perc >= 0.f && time_perc <= 1.f);
|
||||||
//CHECK(_checkPathBounds());
|
//CHECK(_checkPathBounds());
|
||||||
return true;
|
return true;
|
||||||
#undef CHECK
|
#undef CHECK
|
||||||
}
|
}
|
||||||
|
|
||||||
// MONSTER_MOVE packet format limitation for not CatmullRom movement:
|
// MONSTER_MOVE packet format limitation for not CatmullRom movement:
|
||||||
// each vertex offset packed into 11 bytes
|
// each vertex offset packed into 11 bytes
|
||||||
bool MoveSplineInitArgs::_checkPathBounds() const
|
bool MoveSplineInitArgs::_checkPathBounds() const
|
||||||
{
|
|
||||||
if (!(flags & MoveSplineFlag::Mask_CatmullRom) && path.size() > 2)
|
|
||||||
{
|
{
|
||||||
enum{
|
if (!(flags & MoveSplineFlag::Mask_CatmullRom) && path.size() > 2)
|
||||||
MAX_OFFSET = (1 << 11) / 2,
|
|
||||||
};
|
|
||||||
Vector3 middle = (path.front()+path.back()) / 2;
|
|
||||||
Vector3 offset;
|
|
||||||
for (uint32 i = 1; i < path.size()-1; ++i)
|
|
||||||
{
|
{
|
||||||
offset = path[i] - middle;
|
enum
|
||||||
if (fabs(offset.x) >= MAX_OFFSET || fabs(offset.y) >= MAX_OFFSET || fabs(offset.z) >= MAX_OFFSET)
|
|
||||||
{
|
{
|
||||||
sLog.outError("MoveSplineInitArgs::_checkPathBounds check failed");
|
MAX_OFFSET = (1 << 11) / 2,
|
||||||
return false;
|
};
|
||||||
|
Vector3 middle = (path.front()+path.back()) / 2;
|
||||||
|
Vector3 offset;
|
||||||
|
for (uint32 i = 1; i < path.size()-1; ++i)
|
||||||
|
{
|
||||||
|
offset = path[i] - middle;
|
||||||
|
if (fabs(offset.x) >= MAX_OFFSET || fabs(offset.y) >= MAX_OFFSET || fabs(offset.z) >= MAX_OFFSET)
|
||||||
|
{
|
||||||
|
sLog.outError("MoveSplineInitArgs::_checkPathBounds check failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ============================================================================================
|
/// ============================================================================================
|
||||||
|
|
||||||
MoveSpline::UpdateResult MoveSpline::_updateState(int32& ms_time_diff)
|
MoveSpline::UpdateResult MoveSpline::_updateState(int32& ms_time_diff)
|
||||||
{
|
|
||||||
if (Finalized())
|
|
||||||
{
|
{
|
||||||
ms_time_diff = 0;
|
if (Finalized())
|
||||||
return Result_Arrived;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateResult result = Result_None;
|
|
||||||
|
|
||||||
int32 minimal_diff = std::min(ms_time_diff, segment_time_elapsed());
|
|
||||||
MANGOS_ASSERT(minimal_diff >= 0);
|
|
||||||
time_passed += minimal_diff;
|
|
||||||
ms_time_diff -= minimal_diff;
|
|
||||||
|
|
||||||
if (time_passed >= next_timestamp())
|
|
||||||
{
|
|
||||||
++point_Idx;
|
|
||||||
if (point_Idx < spline.last())
|
|
||||||
{
|
{
|
||||||
result = Result_NextSegment;
|
ms_time_diff = 0;
|
||||||
|
return Result_Arrived;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
UpdateResult result = Result_None;
|
||||||
|
|
||||||
|
int32 minimal_diff = std::min(ms_time_diff, segment_time_elapsed());
|
||||||
|
MANGOS_ASSERT(minimal_diff >= 0);
|
||||||
|
time_passed += minimal_diff;
|
||||||
|
ms_time_diff -= minimal_diff;
|
||||||
|
|
||||||
|
if (time_passed >= next_timestamp())
|
||||||
{
|
{
|
||||||
if (spline.isCyclic())
|
++point_Idx;
|
||||||
|
if (point_Idx < spline.last())
|
||||||
{
|
{
|
||||||
point_Idx = spline.first();
|
|
||||||
time_passed = time_passed % Duration();
|
|
||||||
result = Result_NextSegment;
|
result = Result_NextSegment;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_Finalize();
|
if (spline.isCyclic())
|
||||||
ms_time_diff = 0;
|
{
|
||||||
result = Result_Arrived;
|
point_Idx = spline.first();
|
||||||
|
time_passed = time_passed % Duration();
|
||||||
|
result = Result_NextSegment;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_Finalize();
|
||||||
|
ms_time_diff = 0;
|
||||||
|
result = Result_Arrived;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
std::string MoveSpline::ToString() const
|
||||||
}
|
{
|
||||||
|
std::stringstream str;
|
||||||
|
str << "MoveSpline" << std::endl;
|
||||||
|
str << "spline Id: " << GetId() << std::endl;
|
||||||
|
str << "flags: " << splineflags.ToString() << std::endl;
|
||||||
|
if (splineflags.final_angle)
|
||||||
|
str << "facing angle: " << facing.angle;
|
||||||
|
else if (splineflags.final_target)
|
||||||
|
str << "facing target: " << facing.target;
|
||||||
|
else if (splineflags.final_point)
|
||||||
|
str << "facing point: " << facing.f.x << " " << facing.f.y << " " << facing.f.z;
|
||||||
|
str << std::endl;
|
||||||
|
str << "time passed: " << time_passed << std::endl;
|
||||||
|
str << "total time: " << Duration() << std::endl;
|
||||||
|
str << "spline point Id: " << point_Idx << std::endl;
|
||||||
|
str << "path point Id: " << currentPathIdx() << std::endl;
|
||||||
|
str << spline.ToString();
|
||||||
|
return str.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::string MoveSpline::ToString() const
|
void MoveSpline::_Finalize()
|
||||||
{
|
{
|
||||||
std::stringstream str;
|
splineflags.done = true;
|
||||||
str << "MoveSpline" << std::endl;
|
point_Idx = spline.last() - 1;
|
||||||
str << "spline Id: " << GetId() << std::endl;
|
time_passed = Duration();
|
||||||
str << "flags: " << splineflags.ToString() << std::endl;
|
}
|
||||||
if (splineflags.final_angle)
|
|
||||||
str << "facing angle: " << facing.angle;
|
|
||||||
else if (splineflags.final_target)
|
|
||||||
str << "facing target: " << facing.target;
|
|
||||||
else if(splineflags.final_point)
|
|
||||||
str << "facing point: " << facing.f.x << " " << facing.f.y << " " << facing.f.z;
|
|
||||||
str << std::endl;
|
|
||||||
str << "time passed: " << time_passed << std::endl;
|
|
||||||
str << "total time: " << Duration() << std::endl;
|
|
||||||
str << "spline point Id: " << point_Idx << std::endl;
|
|
||||||
str << "path point Id: " << currentPathIdx() << std::endl;
|
|
||||||
str << spline.ToString();
|
|
||||||
return str.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MoveSpline::_Finalize()
|
int32 MoveSpline::currentPathIdx() const
|
||||||
{
|
{
|
||||||
splineflags.done = true;
|
int32 point = point_Idx_offset + point_Idx - spline.first() + (int)Finalized();
|
||||||
point_Idx = spline.last() - 1;
|
if (isCyclic())
|
||||||
time_passed = Duration();
|
point = point % (spline.last()-spline.first());
|
||||||
}
|
return point;
|
||||||
|
}
|
||||||
int32 MoveSpline::currentPathIdx() const
|
|
||||||
{
|
|
||||||
int32 point = point_Idx_offset + point_Idx - spline.first() + (int)Finalized();
|
|
||||||
if (isCyclic())
|
|
||||||
point = point % (spline.last()-spline.first());
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,88 +39,89 @@ namespace Movement
|
||||||
// point can have vertical acceleration motion componemt(used in fall, parabolic movement)
|
// point can have vertical acceleration motion componemt(used in fall, parabolic movement)
|
||||||
class MoveSpline
|
class MoveSpline
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Spline<int32> MySpline;
|
typedef Spline<int32> MySpline;
|
||||||
enum UpdateResult{
|
enum UpdateResult
|
||||||
Result_None = 0x01,
|
{
|
||||||
Result_Arrived = 0x02,
|
Result_None = 0x01,
|
||||||
Result_NextCycle = 0x04,
|
Result_Arrived = 0x02,
|
||||||
Result_NextSegment = 0x08,
|
Result_NextCycle = 0x04,
|
||||||
};
|
Result_NextSegment = 0x08,
|
||||||
friend class PacketBuilder;
|
};
|
||||||
protected:
|
friend class PacketBuilder;
|
||||||
MySpline spline;
|
protected:
|
||||||
|
MySpline spline;
|
||||||
|
|
||||||
FacingInfo facing;
|
FacingInfo facing;
|
||||||
|
|
||||||
uint32 m_Id;
|
uint32 m_Id;
|
||||||
|
|
||||||
MoveSplineFlag splineflags;
|
MoveSplineFlag splineflags;
|
||||||
|
|
||||||
int32 time_passed;
|
int32 time_passed;
|
||||||
// currently duration mods are unused, but its _currently_
|
// currently duration mods are unused, but its _currently_
|
||||||
//float duration_mod;
|
//float duration_mod;
|
||||||
//float duration_mod_next;
|
//float duration_mod_next;
|
||||||
float vertical_acceleration;
|
float vertical_acceleration;
|
||||||
float initialOrientation;
|
float initialOrientation;
|
||||||
int32 effect_start_time;
|
int32 effect_start_time;
|
||||||
int32 point_Idx;
|
int32 point_Idx;
|
||||||
int32 point_Idx_offset;
|
int32 point_Idx_offset;
|
||||||
|
|
||||||
void init_spline(const MoveSplineInitArgs& args);
|
void init_spline(const MoveSplineInitArgs& args);
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
const MySpline::ControlArray& getPath() const { return spline.getPoints();}
|
const MySpline::ControlArray& getPath() const { return spline.getPoints();}
|
||||||
void computeParabolicElevation(float& el) const;
|
void computeParabolicElevation(float& el) const;
|
||||||
void computeFallElevation(float& el) const;
|
void computeFallElevation(float& el) const;
|
||||||
|
|
||||||
UpdateResult _updateState(int32& ms_time_diff);
|
UpdateResult _updateState(int32& ms_time_diff);
|
||||||
int32 next_timestamp() const { return spline.length(point_Idx+1);}
|
int32 next_timestamp() const { return spline.length(point_Idx+1);}
|
||||||
int32 segment_time_elapsed() const { return next_timestamp()-time_passed;}
|
int32 segment_time_elapsed() const { return next_timestamp()-time_passed;}
|
||||||
int32 timeElapsed() const { return Duration() - time_passed;}
|
int32 timeElapsed() const { return Duration() - time_passed;}
|
||||||
int32 timePassed() const { return time_passed;}
|
int32 timePassed() const { return time_passed;}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const MySpline& _Spline() const { return spline;}
|
const MySpline& _Spline() const { return spline;}
|
||||||
int32 _currentSplineIdx() const { return point_Idx;}
|
int32 _currentSplineIdx() const { return point_Idx;}
|
||||||
void _Finalize();
|
void _Finalize();
|
||||||
void _Interrupt() { splineflags.done = true;}
|
void _Interrupt() { splineflags.done = true;}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void Initialize(const MoveSplineInitArgs&);
|
void Initialize(const MoveSplineInitArgs&);
|
||||||
bool Initialized() const { return !spline.empty();}
|
bool Initialized() const { return !spline.empty();}
|
||||||
|
|
||||||
explicit MoveSpline();
|
explicit MoveSpline();
|
||||||
|
|
||||||
template<class UpdateHandler>
|
template<class UpdateHandler>
|
||||||
void updateState(int32 difftime, UpdateHandler& handler)
|
void updateState(int32 difftime, UpdateHandler& handler)
|
||||||
{
|
{
|
||||||
MANGOS_ASSERT(Initialized());
|
MANGOS_ASSERT(Initialized());
|
||||||
do
|
do
|
||||||
handler(_updateState(difftime));
|
handler(_updateState(difftime));
|
||||||
while(difftime > 0);
|
while (difftime > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateState(int32 difftime)
|
void updateState(int32 difftime)
|
||||||
{
|
{
|
||||||
MANGOS_ASSERT(Initialized());
|
MANGOS_ASSERT(Initialized());
|
||||||
do _updateState(difftime);
|
do _updateState(difftime);
|
||||||
while(difftime > 0);
|
while (difftime > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Location ComputePosition() const;
|
Location ComputePosition() const;
|
||||||
|
|
||||||
uint32 GetId() const { return m_Id;}
|
uint32 GetId() const { return m_Id;}
|
||||||
bool Finalized() const { return splineflags.done; }
|
bool Finalized() const { return splineflags.done; }
|
||||||
bool isCyclic() const { return splineflags.cyclic;}
|
bool isCyclic() const { return splineflags.cyclic;}
|
||||||
const Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3();}
|
const Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3();}
|
||||||
const Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx+1) : Vector3();}
|
const Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx+1) : Vector3();}
|
||||||
int32 currentPathIdx() const;
|
int32 currentPathIdx() const;
|
||||||
|
|
||||||
int32 Duration() const { return spline.length();}
|
int32 Duration() const { return spline.length();}
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // MANGOSSERVER_MOVEPLINE_H
|
#endif // MANGOSSERVER_MOVEPLINE_H
|
||||||
|
|
|
||||||
|
|
@ -32,106 +32,107 @@ namespace Movement
|
||||||
|
|
||||||
class MoveSplineFlag
|
class MoveSplineFlag
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum eFlags{
|
enum eFlags
|
||||||
None = 0x00000000,
|
{
|
||||||
// x00-xFF(first byte) used as animation Ids storage in pair with Animation flag
|
None = 0x00000000,
|
||||||
Done = 0x00000100,
|
// x00-xFF(first byte) used as animation Ids storage in pair with Animation flag
|
||||||
Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag
|
Done = 0x00000100,
|
||||||
No_Spline = 0x00000400,
|
Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag
|
||||||
Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag
|
No_Spline = 0x00000400,
|
||||||
Walkmode = 0x00001000,
|
Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag
|
||||||
Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation
|
Walkmode = 0x00001000,
|
||||||
OrientationFixed = 0x00004000, // Model orientation fixed
|
Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation
|
||||||
Final_Point = 0x00008000,
|
OrientationFixed = 0x00004000, // Model orientation fixed
|
||||||
Final_Target = 0x00010000,
|
Final_Point = 0x00008000,
|
||||||
Final_Angle = 0x00020000,
|
Final_Target = 0x00010000,
|
||||||
Catmullrom = 0x00040000, // Used Catmullrom interpolation mode
|
Final_Angle = 0x00020000,
|
||||||
Cyclic = 0x00080000, // Movement by cycled spline
|
Catmullrom = 0x00040000, // Used Catmullrom interpolation mode
|
||||||
Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done
|
Cyclic = 0x00080000, // Movement by cycled spline
|
||||||
Animation = 0x00200000, // Plays animation after some time passed
|
Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done
|
||||||
Frozen = 0x00400000, // Will never arrive
|
Animation = 0x00200000, // Plays animation after some time passed
|
||||||
Unknown5 = 0x00800000,
|
Frozen = 0x00400000, // Will never arrive
|
||||||
Unknown6 = 0x01000000,
|
Unknown5 = 0x00800000,
|
||||||
Unknown7 = 0x02000000,
|
Unknown6 = 0x01000000,
|
||||||
Unknown8 = 0x04000000,
|
Unknown7 = 0x02000000,
|
||||||
OrientationInversed = 0x08000000,
|
Unknown8 = 0x04000000,
|
||||||
Unknown10 = 0x10000000,
|
OrientationInversed = 0x08000000,
|
||||||
Unknown11 = 0x20000000,
|
Unknown10 = 0x10000000,
|
||||||
Unknown12 = 0x40000000,
|
Unknown11 = 0x20000000,
|
||||||
Unknown13 = 0x80000000,
|
Unknown12 = 0x40000000,
|
||||||
|
Unknown13 = 0x80000000,
|
||||||
|
|
||||||
// Masks
|
// Masks
|
||||||
Mask_Final_Facing = Final_Point | Final_Target | Final_Angle,
|
Mask_Final_Facing = Final_Point | Final_Target | Final_Angle,
|
||||||
// animation ids stored here, see AnimType enum, used with Animation flag
|
// animation ids stored here, see AnimType enum, used with Animation flag
|
||||||
Mask_Animations = 0xFF,
|
Mask_Animations = 0xFF,
|
||||||
// flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably
|
// flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably
|
||||||
Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done,
|
Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done,
|
||||||
// CatmullRom interpolation mode used
|
// CatmullRom interpolation mode used
|
||||||
Mask_CatmullRom = Flying | Catmullrom,
|
Mask_CatmullRom = Flying | Catmullrom,
|
||||||
// Unused, not suported flags
|
// Unused, not suported flags
|
||||||
Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown5|Unknown6|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13,
|
Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown5|Unknown6|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline uint32& raw() { return (uint32&)*this;}
|
inline uint32& raw() { return (uint32&)*this;}
|
||||||
inline const uint32& raw() const { return (const uint32&)*this;}
|
inline const uint32& raw() const { return (const uint32&)*this;}
|
||||||
|
|
||||||
MoveSplineFlag() { raw() = 0; }
|
MoveSplineFlag() { raw() = 0; }
|
||||||
MoveSplineFlag(uint32 f) { raw() = f; }
|
MoveSplineFlag(uint32 f) { raw() = f; }
|
||||||
MoveSplineFlag(const MoveSplineFlag& f) { raw() = f.raw(); }
|
MoveSplineFlag(const MoveSplineFlag& f) { raw() = f.raw(); }
|
||||||
|
|
||||||
// Constant interface
|
// Constant interface
|
||||||
|
|
||||||
bool isSmooth() const { return raw() & Mask_CatmullRom;}
|
bool isSmooth() const { return raw() & Mask_CatmullRom;}
|
||||||
bool isLinear() const { return !isSmooth();}
|
bool isLinear() const { return !isSmooth();}
|
||||||
bool isFacing() const { return raw() & Mask_Final_Facing;}
|
bool isFacing() const { return raw() & Mask_Final_Facing;}
|
||||||
|
|
||||||
uint8 getAnimationId() const { return animId;}
|
uint8 getAnimationId() const { return animId;}
|
||||||
bool hasAllFlags(uint32 f) const { return (raw() & f) == f;}
|
bool hasAllFlags(uint32 f) const { return (raw() & f) == f;}
|
||||||
bool hasFlag(uint32 f) const { return (raw() & f) != 0;}
|
bool hasFlag(uint32 f) const { return (raw() & f) != 0;}
|
||||||
uint32 operator & (uint32 f) const { return (raw() & f);}
|
uint32 operator & (uint32 f) const { return (raw() & f);}
|
||||||
uint32 operator | (uint32 f) const { return (raw() | f);}
|
uint32 operator | (uint32 f) const { return (raw() | f);}
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
|
|
||||||
// Not constant interface
|
// Not constant interface
|
||||||
|
|
||||||
void operator &= (uint32 f) { raw() &= f;}
|
void operator &= (uint32 f) { raw() &= f;}
|
||||||
void operator |= (uint32 f) { raw() |= f;}
|
void operator |= (uint32 f) { raw() |= f;}
|
||||||
|
|
||||||
void EnableAnimation(uint8 anim) { raw() = raw() & ~(Mask_Animations|Falling|Parabolic) | Animation|anim;}
|
void EnableAnimation(uint8 anim) { raw() = raw() & ~(Mask_Animations|Falling|Parabolic) | Animation|anim;}
|
||||||
void EnableParabolic() { raw() = raw() & ~(Mask_Animations|Falling|Animation) | Parabolic;}
|
void EnableParabolic() { raw() = raw() & ~(Mask_Animations|Falling|Animation) | Parabolic;}
|
||||||
void EnableFalling() { raw() = raw() & ~(Mask_Animations|Parabolic|Animation) | Falling;}
|
void EnableFalling() { raw() = raw() & ~(Mask_Animations|Parabolic|Animation) | Falling;}
|
||||||
void EnableFlying() { raw() = raw() & ~Catmullrom | Flying; }
|
void EnableFlying() { raw() = raw() & ~Catmullrom | Flying; }
|
||||||
void EnableCatmullRom() { raw() = raw() & ~Flying | Catmullrom; }
|
void EnableCatmullRom() { raw() = raw() & ~Flying | Catmullrom; }
|
||||||
void EnableFacingPoint() { raw() = raw() & ~Mask_Final_Facing | Final_Point;}
|
void EnableFacingPoint() { raw() = raw() & ~Mask_Final_Facing | Final_Point;}
|
||||||
void EnableFacingAngle() { raw() = raw() & ~Mask_Final_Facing | Final_Angle;}
|
void EnableFacingAngle() { raw() = raw() & ~Mask_Final_Facing | Final_Angle;}
|
||||||
void EnableFacingTarget() { raw() = raw() & ~Mask_Final_Facing | Final_Target;}
|
void EnableFacingTarget() { raw() = raw() & ~Mask_Final_Facing | Final_Target;}
|
||||||
|
|
||||||
uint8 animId : 8;
|
uint8 animId : 8;
|
||||||
bool done : 1;
|
bool done : 1;
|
||||||
bool falling : 1;
|
bool falling : 1;
|
||||||
bool no_spline : 1;
|
bool no_spline : 1;
|
||||||
bool parabolic : 1;
|
bool parabolic : 1;
|
||||||
bool walkmode : 1;
|
bool walkmode : 1;
|
||||||
bool flying : 1;
|
bool flying : 1;
|
||||||
bool orientationFixed : 1;
|
bool orientationFixed : 1;
|
||||||
bool final_point : 1;
|
bool final_point : 1;
|
||||||
bool final_target : 1;
|
bool final_target : 1;
|
||||||
bool final_angle : 1;
|
bool final_angle : 1;
|
||||||
bool catmullrom : 1;
|
bool catmullrom : 1;
|
||||||
bool cyclic : 1;
|
bool cyclic : 1;
|
||||||
bool enter_cycle : 1;
|
bool enter_cycle : 1;
|
||||||
bool animation : 1;
|
bool animation : 1;
|
||||||
bool frozen : 1;
|
bool frozen : 1;
|
||||||
bool unknown5 : 1;
|
bool unknown5 : 1;
|
||||||
bool unknown6 : 1;
|
bool unknown6 : 1;
|
||||||
bool unknown7 : 1;
|
bool unknown7 : 1;
|
||||||
bool unknown8 : 1;
|
bool unknown8 : 1;
|
||||||
bool orientationInversed : 1;
|
bool orientationInversed : 1;
|
||||||
bool unknown10 : 1;
|
bool unknown10 : 1;
|
||||||
bool unknown11 : 1;
|
bool unknown11 : 1;
|
||||||
bool unknown12 : 1;
|
bool unknown12 : 1;
|
||||||
bool unknown13 : 1;
|
bool unknown13 : 1;
|
||||||
};
|
};
|
||||||
#if defined( __GNUC__ )
|
#if defined( __GNUC__ )
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Movement
|
||||||
{
|
{
|
||||||
if (moveFlags & MOVEFLAG_FLYING)
|
if (moveFlags & MOVEFLAG_FLYING)
|
||||||
{
|
{
|
||||||
if ( moveFlags & MOVEFLAG_BACKWARD /*&& speed_obj.flight >= speed_obj.flight_back*/ )
|
if (moveFlags & MOVEFLAG_BACKWARD /*&& speed_obj.flight >= speed_obj.flight_back*/)
|
||||||
return MOVE_FLIGHT_BACK;
|
return MOVE_FLIGHT_BACK;
|
||||||
else
|
else
|
||||||
return MOVE_FLIGHT;
|
return MOVE_FLIGHT;
|
||||||
|
|
@ -102,7 +102,7 @@ namespace Movement
|
||||||
args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_FLYING|MOVEFLAG_LEVITATING));
|
args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_FLYING|MOVEFLAG_LEVITATING));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveSplineInit::SetFacing(const Unit * target)
|
void MoveSplineInit::SetFacing(const Unit* target)
|
||||||
{
|
{
|
||||||
args.flags.EnableFacingTarget();
|
args.flags.EnableFacingTarget();
|
||||||
args.facing.target = target->GetObjectGuid().GetRawValue();
|
args.facing.target = target->GetObjectGuid().GetRawValue();
|
||||||
|
|
|
||||||
|
|
@ -38,86 +38,86 @@ namespace Movement
|
||||||
*/
|
*/
|
||||||
class MANGOS_DLL_SPEC MoveSplineInit
|
class MANGOS_DLL_SPEC MoveSplineInit
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit MoveSplineInit(Unit& m);
|
explicit MoveSplineInit(Unit& m);
|
||||||
|
|
||||||
/* Final pass of initialization that launches spline movement.
|
/* Final pass of initialization that launches spline movement.
|
||||||
* @return duration - estimated travel time
|
* @return duration - estimated travel time
|
||||||
*/
|
*/
|
||||||
int32 Launch();
|
int32 Launch();
|
||||||
|
|
||||||
/* Adds movement by parabolic trajectory
|
/* Adds movement by parabolic trajectory
|
||||||
* @param amplitude - the maximum height of parabola, value could be negative and positive
|
* @param amplitude - the maximum height of parabola, value could be negative and positive
|
||||||
* @param start_time - delay between movement starting time and beginning to move by parabolic trajectory
|
* @param start_time - delay between movement starting time and beginning to move by parabolic trajectory
|
||||||
* can't be combined with final animation
|
* can't be combined with final animation
|
||||||
*/
|
*/
|
||||||
void SetParabolic(float amplitude, float start_time);
|
void SetParabolic(float amplitude, float start_time);
|
||||||
/* Plays animation after movement done
|
/* Plays animation after movement done
|
||||||
* can't be combined with parabolic movement
|
* can't be combined with parabolic movement
|
||||||
*/
|
*/
|
||||||
void SetAnimation(AnimType anim);
|
void SetAnimation(AnimType anim);
|
||||||
|
|
||||||
/* Adds final facing animation
|
/* Adds final facing animation
|
||||||
* sets unit's facing to specified point/angle after all path done
|
* sets unit's facing to specified point/angle after all path done
|
||||||
* you can have only one final facing: previous will be overriden
|
* you can have only one final facing: previous will be overriden
|
||||||
*/
|
*/
|
||||||
void SetFacing(float angle);
|
void SetFacing(float angle);
|
||||||
void SetFacing(Vector3 const& point);
|
void SetFacing(Vector3 const& point);
|
||||||
void SetFacing(const Unit * target);
|
void SetFacing(const Unit* target);
|
||||||
|
|
||||||
/* Initializes movement by path
|
/* Initializes movement by path
|
||||||
* @param path - array of points, shouldn't be empty
|
* @param path - array of points, shouldn't be empty
|
||||||
* @param pointId - Id of fisrt point of the path. Example: when third path point will be done it will notify that pointId + 3 done
|
* @param pointId - Id of fisrt point of the path. Example: when third path point will be done it will notify that pointId + 3 done
|
||||||
*/
|
*/
|
||||||
void MovebyPath(const PointsArray& path, int32 pointId = 0);
|
void MovebyPath(const PointsArray& path, int32 pointId = 0);
|
||||||
|
|
||||||
/* Initializes simple A to B mition, A is current unit's position, B is destination
|
/* Initializes simple A to B mition, A is current unit's position, B is destination
|
||||||
*/
|
*/
|
||||||
void MoveTo(const Vector3& destination, bool generatePath = false, bool forceDestination = false);
|
void MoveTo(const Vector3& destination, bool generatePath = false, bool forceDestination = false);
|
||||||
void MoveTo(float x, float y, float z, bool generatePath = false, bool forceDestination = false);
|
void MoveTo(float x, float y, float z, bool generatePath = false, bool forceDestination = false);
|
||||||
|
|
||||||
/* Sets Id of fisrt point of the path. When N-th path point will be done ILisener will notify that pointId + N done
|
/* Sets Id of fisrt point of the path. When N-th path point will be done ILisener will notify that pointId + N done
|
||||||
* Needed for waypoint movement where path splitten into parts
|
* Needed for waypoint movement where path splitten into parts
|
||||||
*/
|
*/
|
||||||
void SetFirstPointId(int32 pointId) { args.path_Idx_offset = pointId; }
|
void SetFirstPointId(int32 pointId) { args.path_Idx_offset = pointId; }
|
||||||
|
|
||||||
/* Enables CatmullRom spline interpolation mode(makes path smooth)
|
/* Enables CatmullRom spline interpolation mode(makes path smooth)
|
||||||
* if not enabled linear spline mode will be choosen. Disabled by default
|
* if not enabled linear spline mode will be choosen. Disabled by default
|
||||||
*/
|
*/
|
||||||
void SetSmooth();
|
void SetSmooth();
|
||||||
/* Enables CatmullRom spline interpolation mode, enables flying animation. Disabled by default
|
/* Enables CatmullRom spline interpolation mode, enables flying animation. Disabled by default
|
||||||
*/
|
*/
|
||||||
void SetFly();
|
void SetFly();
|
||||||
/* Enables walk mode. Disabled by default
|
/* Enables walk mode. Disabled by default
|
||||||
*/
|
*/
|
||||||
void SetWalk(bool enable);
|
void SetWalk(bool enable);
|
||||||
/* Makes movement cyclic. Disabled by default
|
/* Makes movement cyclic. Disabled by default
|
||||||
*/
|
*/
|
||||||
void SetCyclic();
|
void SetCyclic();
|
||||||
/* Enables falling mode. Disabled by default
|
/* Enables falling mode. Disabled by default
|
||||||
*/
|
*/
|
||||||
void SetFall();
|
void SetFall();
|
||||||
/* Inverses unit model orientation. Disabled by default
|
/* Inverses unit model orientation. Disabled by default
|
||||||
*/
|
*/
|
||||||
void SetOrientationInversed();
|
void SetOrientationInversed();
|
||||||
/* Fixes unit's model rotation. Disabled by default
|
/* Fixes unit's model rotation. Disabled by default
|
||||||
*/
|
*/
|
||||||
void SetOrientationFixed(bool enable);
|
void SetOrientationFixed(bool enable);
|
||||||
|
|
||||||
/* Sets the velocity (in case you want to have custom movement velocity)
|
/* Sets the velocity (in case you want to have custom movement velocity)
|
||||||
* if no set, speed will be selected based on unit's speeds and current movement mode
|
* if no set, speed will be selected based on unit's speeds and current movement mode
|
||||||
* Has no effect if falling mode enabled
|
* Has no effect if falling mode enabled
|
||||||
* velocity shouldn't be negative
|
* velocity shouldn't be negative
|
||||||
*/
|
*/
|
||||||
void SetVelocity(float velocity);
|
void SetVelocity(float velocity);
|
||||||
|
|
||||||
PointsArray& Path() { return args.path; }
|
PointsArray& Path() { return args.path; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
MoveSplineInitArgs args;
|
MoveSplineInitArgs args;
|
||||||
Unit& unit;
|
Unit& unit;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void MoveSplineInit::SetFly() { args.flags.EnableFlying();}
|
inline void MoveSplineInit::SetFly() { args.flags.EnableFlying();}
|
||||||
|
|
@ -125,7 +125,7 @@ namespace Movement
|
||||||
inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom();}
|
inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom();}
|
||||||
inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true;}
|
inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true;}
|
||||||
inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();}
|
inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();}
|
||||||
inline void MoveSplineInit::SetVelocity(float vel){ args.velocity = vel;}
|
inline void MoveSplineInit::SetVelocity(float vel) { args.velocity = vel;}
|
||||||
inline void MoveSplineInit::SetOrientationInversed() { args.flags.orientationInversed = true;}
|
inline void MoveSplineInit::SetOrientationInversed() { args.flags.orientationInversed = true;}
|
||||||
inline void MoveSplineInit::SetOrientationFixed(bool enable) { args.flags.orientationFixed = enable;}
|
inline void MoveSplineInit::SetOrientationFixed(bool enable) { args.flags.orientationFixed = enable;}
|
||||||
|
|
||||||
|
|
@ -143,7 +143,7 @@ namespace Movement
|
||||||
|
|
||||||
inline void MoveSplineInit::MoveTo(const Vector3& dest, bool generatePath, bool forceDestination)
|
inline void MoveSplineInit::MoveTo(const Vector3& dest, bool generatePath, bool forceDestination)
|
||||||
{
|
{
|
||||||
if(generatePath)
|
if (generatePath)
|
||||||
{
|
{
|
||||||
PathFinder path(&unit);
|
PathFinder path(&unit);
|
||||||
path.calculate(dest.x, dest.y, dest.z, forceDestination);
|
path.calculate(dest.x, dest.y, dest.z, forceDestination);
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,10 @@ namespace Movement
|
||||||
|
|
||||||
union FacingInfo
|
union FacingInfo
|
||||||
{
|
{
|
||||||
struct{
|
struct
|
||||||
|
{
|
||||||
float x,y,z;
|
float x,y,z;
|
||||||
}f;
|
} f;
|
||||||
uint64 target;
|
uint64 target;
|
||||||
float angle;
|
float angle;
|
||||||
|
|
||||||
|
|
@ -41,26 +42,26 @@ namespace Movement
|
||||||
|
|
||||||
struct MoveSplineInitArgs
|
struct MoveSplineInitArgs
|
||||||
{
|
{
|
||||||
MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0),
|
MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0),
|
||||||
velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f)
|
velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f)
|
||||||
{
|
{
|
||||||
path.reserve(path_capacity);
|
path.reserve(path_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
PointsArray path;
|
PointsArray path;
|
||||||
FacingInfo facing;
|
FacingInfo facing;
|
||||||
MoveSplineFlag flags;
|
MoveSplineFlag flags;
|
||||||
int32 path_Idx_offset;
|
int32 path_Idx_offset;
|
||||||
float velocity;
|
float velocity;
|
||||||
float parabolic_amplitude;
|
float parabolic_amplitude;
|
||||||
float time_perc;
|
float time_perc;
|
||||||
uint32 splineId;
|
uint32 splineId;
|
||||||
float initialOrientation;
|
float initialOrientation;
|
||||||
|
|
||||||
/** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */
|
/** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */
|
||||||
bool Validate() const;
|
bool Validate() const;
|
||||||
private:
|
private:
|
||||||
bool _checkPathBounds() const;
|
bool _checkPathBounds() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,23 +56,23 @@ namespace Movement
|
||||||
data << move_spline.spline.getPoint(move_spline.spline.first());
|
data << move_spline.spline.getPoint(move_spline.spline.first());
|
||||||
data << move_spline.GetId();
|
data << move_spline.GetId();
|
||||||
|
|
||||||
switch(splineflags & MoveSplineFlag::Mask_Final_Facing)
|
switch (splineflags & MoveSplineFlag::Mask_Final_Facing)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
data << uint8(MonsterMoveNormal);
|
data << uint8(MonsterMoveNormal);
|
||||||
break;
|
break;
|
||||||
case MoveSplineFlag::Final_Target:
|
case MoveSplineFlag::Final_Target:
|
||||||
data << uint8(MonsterMoveFacingTarget);
|
data << uint8(MonsterMoveFacingTarget);
|
||||||
data << move_spline.facing.target;
|
data << move_spline.facing.target;
|
||||||
break;
|
break;
|
||||||
case MoveSplineFlag::Final_Angle:
|
case MoveSplineFlag::Final_Angle:
|
||||||
data << uint8(MonsterMoveFacingAngle);
|
data << uint8(MonsterMoveFacingAngle);
|
||||||
data << move_spline.facing.angle;
|
data << move_spline.facing.angle;
|
||||||
break;
|
break;
|
||||||
case MoveSplineFlag::Final_Point:
|
case MoveSplineFlag::Final_Point:
|
||||||
data << uint8(MonsterMoveFacingSpot);
|
data << uint8(MonsterMoveFacingSpot);
|
||||||
data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
|
data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add fake Enter_Cycle flag - needed for client-side cyclic movement (client will erase first spline vertex after first cycle done)
|
// add fake Enter_Cycle flag - needed for client-side cyclic movement (client will erase first spline vertex after first cycle done)
|
||||||
|
|
@ -97,7 +97,7 @@ namespace Movement
|
||||||
void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data)
|
void WriteLinearPath(const Spline<int32>& spline, ByteBuffer& data)
|
||||||
{
|
{
|
||||||
uint32 last_idx = spline.getPointCount() - 3;
|
uint32 last_idx = spline.getPointCount() - 3;
|
||||||
const Vector3 * real_path = &spline.getPoint(1);
|
const Vector3* real_path = &spline.getPoint(1);
|
||||||
|
|
||||||
data << last_idx;
|
data << last_idx;
|
||||||
data << real_path[last_idx]; // destination
|
data << real_path[last_idx]; // destination
|
||||||
|
|
@ -106,7 +106,7 @@ namespace Movement
|
||||||
Vector3 middle = (real_path[0] + real_path[last_idx]) / 2.f;
|
Vector3 middle = (real_path[0] + real_path[last_idx]) / 2.f;
|
||||||
Vector3 offset;
|
Vector3 offset;
|
||||||
// first and last points already appended
|
// first and last points already appended
|
||||||
for(uint32 i = 1; i < last_idx; ++i)
|
for (uint32 i = 1; i < last_idx; ++i)
|
||||||
{
|
{
|
||||||
offset = middle - real_path[i];
|
offset = middle - real_path[i];
|
||||||
data.appendPackXYZ(offset.x, offset.y, offset.z);
|
data.appendPackXYZ(offset.x, offset.y, offset.z);
|
||||||
|
|
@ -164,7 +164,7 @@ namespace Movement
|
||||||
{
|
{
|
||||||
data << move_spline.facing.target;
|
data << move_spline.facing.target;
|
||||||
}
|
}
|
||||||
else if(splineFlags.final_point)
|
else if (splineFlags.final_point)
|
||||||
{
|
{
|
||||||
data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
|
data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,11 @@ namespace Movement
|
||||||
class MoveSpline;
|
class MoveSpline;
|
||||||
class PacketBuilder
|
class PacketBuilder
|
||||||
{
|
{
|
||||||
static void WriteCommonMonsterMovePart(const MoveSpline& mov, WorldPacket& data);
|
static void WriteCommonMonsterMovePart(const MoveSpline& mov, WorldPacket& data);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static void WriteMonsterMove(const MoveSpline& mov, WorldPacket& data);
|
static void WriteMonsterMove(const MoveSpline& mov, WorldPacket& data);
|
||||||
static void WriteCreate(const MoveSpline& mov, ByteBuffer& data);
|
static void WriteCreate(const MoveSpline& mov, ByteBuffer& data);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // MANGOSSERVER_PACKET_BUILDER_H
|
#endif // MANGOSSERVER_PACKET_BUILDER_H
|
||||||
|
|
|
||||||
|
|
@ -20,288 +20,289 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <G3D/Matrix4.h>
|
#include <G3D/Matrix4.h>
|
||||||
|
|
||||||
namespace Movement{
|
namespace Movement
|
||||||
|
|
||||||
SplineBase::EvaluationMethtod SplineBase::evaluators[SplineBase::ModesEnd] =
|
|
||||||
{
|
{
|
||||||
&SplineBase::EvaluateLinear,
|
|
||||||
&SplineBase::EvaluateCatmullRom,
|
|
||||||
&SplineBase::EvaluateBezier3,
|
|
||||||
(EvaluationMethtod)&SplineBase::UninitializedSpline,
|
|
||||||
};
|
|
||||||
|
|
||||||
SplineBase::EvaluationMethtod SplineBase::derivative_evaluators[SplineBase::ModesEnd] =
|
SplineBase::EvaluationMethtod SplineBase::evaluators[SplineBase::ModesEnd] =
|
||||||
{
|
{
|
||||||
&SplineBase::EvaluateDerivativeLinear,
|
&SplineBase::EvaluateLinear,
|
||||||
&SplineBase::EvaluateDerivativeCatmullRom,
|
&SplineBase::EvaluateCatmullRom,
|
||||||
&SplineBase::EvaluateDerivativeBezier3,
|
&SplineBase::EvaluateBezier3,
|
||||||
(EvaluationMethtod)&SplineBase::UninitializedSpline,
|
(EvaluationMethtod)& SplineBase::UninitializedSpline,
|
||||||
};
|
};
|
||||||
|
|
||||||
SplineBase::SegLenghtMethtod SplineBase::seglengths[SplineBase::ModesEnd] =
|
SplineBase::EvaluationMethtod SplineBase::derivative_evaluators[SplineBase::ModesEnd] =
|
||||||
{
|
{
|
||||||
&SplineBase::SegLengthLinear,
|
&SplineBase::EvaluateDerivativeLinear,
|
||||||
&SplineBase::SegLengthCatmullRom,
|
&SplineBase::EvaluateDerivativeCatmullRom,
|
||||||
&SplineBase::SegLengthBezier3,
|
&SplineBase::EvaluateDerivativeBezier3,
|
||||||
(SegLenghtMethtod)&SplineBase::UninitializedSpline,
|
(EvaluationMethtod)& SplineBase::UninitializedSpline,
|
||||||
};
|
};
|
||||||
|
|
||||||
SplineBase::InitMethtod SplineBase::initializers[SplineBase::ModesEnd] =
|
SplineBase::SegLenghtMethtod SplineBase::seglengths[SplineBase::ModesEnd] =
|
||||||
{
|
{
|
||||||
//&SplineBase::InitLinear,
|
&SplineBase::SegLengthLinear,
|
||||||
&SplineBase::InitCatmullRom, // we should use catmullrom initializer even for linear mode! (client's internal structure limitation)
|
&SplineBase::SegLengthCatmullRom,
|
||||||
&SplineBase::InitCatmullRom,
|
&SplineBase::SegLengthBezier3,
|
||||||
&SplineBase::InitBezier3,
|
(SegLenghtMethtod)& SplineBase::UninitializedSpline,
|
||||||
(InitMethtod)&SplineBase::UninitializedSpline,
|
};
|
||||||
};
|
|
||||||
|
SplineBase::InitMethtod SplineBase::initializers[SplineBase::ModesEnd] =
|
||||||
|
{
|
||||||
|
//&SplineBase::InitLinear,
|
||||||
|
&SplineBase::InitCatmullRom, // we should use catmullrom initializer even for linear mode! (client's internal structure limitation)
|
||||||
|
&SplineBase::InitCatmullRom,
|
||||||
|
&SplineBase::InitBezier3,
|
||||||
|
(InitMethtod)& SplineBase::UninitializedSpline,
|
||||||
|
};
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
#pragma region evaluation methtods
|
#pragma region evaluation methtods
|
||||||
|
|
||||||
using G3D::Matrix4;
|
using G3D::Matrix4;
|
||||||
static const Matrix4 s_catmullRomCoeffs(
|
static const Matrix4 s_catmullRomCoeffs(
|
||||||
-0.5f, 1.5f,-1.5f, 0.5f,
|
-0.5f, 1.5f,-1.5f, 0.5f,
|
||||||
1.f, -2.5f, 2.f, -0.5f,
|
1.f, -2.5f, 2.f, -0.5f,
|
||||||
-0.5f, 0.f, 0.5f, 0.f,
|
-0.5f, 0.f, 0.5f, 0.f,
|
||||||
0.f, 1.f, 0.f, 0.f);
|
0.f, 1.f, 0.f, 0.f);
|
||||||
|
|
||||||
static const Matrix4 s_Bezier3Coeffs(
|
static const Matrix4 s_Bezier3Coeffs(
|
||||||
-1.f, 3.f, -3.f, 1.f,
|
-1.f, 3.f, -3.f, 1.f,
|
||||||
3.f, -6.f, 3.f, 0.f,
|
3.f, -6.f, 3.f, 0.f,
|
||||||
-3.f, 3.f, 0.f, 0.f,
|
-3.f, 3.f, 0.f, 0.f,
|
||||||
1.f, 0.f, 0.f, 0.f);
|
1.f, 0.f, 0.f, 0.f);
|
||||||
|
|
||||||
/* classic view:
|
/* classic view:
|
||||||
inline void C_Evaluate(const Vector3 *vertice, float t, const float (&matrix)[4][4], Vector3 &position)
|
inline void C_Evaluate(const Vector3 *vertice, float t, const float (&matrix)[4][4], Vector3 &position)
|
||||||
{
|
|
||||||
Vector3 tvec(t*t*t, t*t, t);
|
|
||||||
int i = 0;
|
|
||||||
double c;
|
|
||||||
double x = 0, y = 0, z = 0;
|
|
||||||
while ( i < 4 )
|
|
||||||
{
|
{
|
||||||
c = matrix[0][i]*tvec.x + matrix[1][i]*tvec.y + matrix[2][i]*tvec.z + matrix[3][i];
|
Vector3 tvec(t*t*t, t*t, t);
|
||||||
|
int i = 0;
|
||||||
|
double c;
|
||||||
|
double x = 0, y = 0, z = 0;
|
||||||
|
while ( i < 4 )
|
||||||
|
{
|
||||||
|
c = matrix[0][i]*tvec.x + matrix[1][i]*tvec.y + matrix[2][i]*tvec.z + matrix[3][i];
|
||||||
|
|
||||||
x += c * vertice->x;
|
x += c * vertice->x;
|
||||||
y += c * vertice->y;
|
y += c * vertice->y;
|
||||||
z += c * vertice->z;
|
z += c * vertice->z;
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
++vertice;
|
++vertice;
|
||||||
|
}
|
||||||
|
|
||||||
|
position.x = x;
|
||||||
|
position.y = y;
|
||||||
|
position.z = z;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
inline void C_Evaluate(const Vector3* vertice, float t, const Matrix4& matr, Vector3& result)
|
||||||
|
{
|
||||||
|
Vector4 tvec(t*t*t, t*t, t, 1.f);
|
||||||
|
Vector4 weights(tvec * matr);
|
||||||
|
|
||||||
|
result = vertice[0] * weights[0] + vertice[1] * weights[1]
|
||||||
|
+ vertice[2] * weights[2] + vertice[3] * weights[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
position.x = x;
|
inline void C_Evaluate_Derivative(const Vector3* vertice, float t, const Matrix4& matr, Vector3& result)
|
||||||
position.y = y;
|
|
||||||
position.z = z;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
inline void C_Evaluate(const Vector3 *vertice, float t, const Matrix4& matr, Vector3 &result)
|
|
||||||
{
|
|
||||||
Vector4 tvec(t*t*t, t*t, t, 1.f);
|
|
||||||
Vector4 weights(tvec * matr);
|
|
||||||
|
|
||||||
result = vertice[0] * weights[0] + vertice[1] * weights[1]
|
|
||||||
+ vertice[2] * weights[2] + vertice[3] * weights[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void C_Evaluate_Derivative(const Vector3 *vertice, float t, const Matrix4& matr, Vector3 &result)
|
|
||||||
{
|
|
||||||
Vector4 tvec(3.f*t*t, 2.f*t, 1.f, 0.f);
|
|
||||||
Vector4 weights(tvec * matr);
|
|
||||||
|
|
||||||
result = vertice[0] * weights[0] + vertice[1] * weights[1]
|
|
||||||
+ vertice[2] * weights[2] + vertice[3] * weights[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineBase::EvaluateLinear(index_type index, float u, Vector3& result) const
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
|
||||||
result = points[index] + (points[index+1] - points[index]) * u;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineBase::EvaluateCatmullRom( index_type index, float t, Vector3& result) const
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
|
||||||
C_Evaluate(&points[index - 1], t, s_catmullRomCoeffs, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineBase::EvaluateBezier3(index_type index, float t, Vector3& result) const
|
|
||||||
{
|
|
||||||
index *= 3u;
|
|
||||||
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
|
||||||
C_Evaluate(&points[index], t, s_Bezier3Coeffs, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineBase::EvaluateDerivativeLinear(index_type index, float, Vector3& result) const
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
|
||||||
result = points[index+1] - points[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineBase::EvaluateDerivativeCatmullRom(index_type index, float t, Vector3& result) const
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
|
||||||
C_Evaluate_Derivative(&points[index - 1], t, s_catmullRomCoeffs, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineBase::EvaluateDerivativeBezier3(index_type index, float t, Vector3& result) const
|
|
||||||
{
|
|
||||||
index *= 3u;
|
|
||||||
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
|
||||||
C_Evaluate_Derivative(&points[index], t, s_Bezier3Coeffs, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
float SplineBase::SegLengthLinear(index_type index) const
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
|
||||||
return (points[index] - points[index+1]).length();
|
|
||||||
}
|
|
||||||
|
|
||||||
float SplineBase::SegLengthCatmullRom( index_type index ) const
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
|
||||||
|
|
||||||
Vector3 curPos, nextPos;
|
|
||||||
const Vector3 * p = &points[index - 1];
|
|
||||||
curPos = nextPos = p[1];
|
|
||||||
|
|
||||||
index_type i = 1;
|
|
||||||
double length = 0;
|
|
||||||
while (i <= STEPS_PER_SEGMENT)
|
|
||||||
{
|
{
|
||||||
C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_catmullRomCoeffs, nextPos);
|
Vector4 tvec(3.f*t*t, 2.f*t, 1.f, 0.f);
|
||||||
length += (nextPos - curPos).length();
|
Vector4 weights(tvec * matr);
|
||||||
|
|
||||||
|
result = vertice[0] * weights[0] + vertice[1] * weights[1]
|
||||||
|
+ vertice[2] * weights[2] + vertice[3] * weights[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateLinear(index_type index, float u, Vector3& result) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
result = points[index] + (points[index+1] - points[index]) * u;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateCatmullRom(index_type index, float t, Vector3& result) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
C_Evaluate(&points[index - 1], t, s_catmullRomCoeffs, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateBezier3(index_type index, float t, Vector3& result) const
|
||||||
|
{
|
||||||
|
index *= 3u;
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
C_Evaluate(&points[index], t, s_Bezier3Coeffs, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateDerivativeLinear(index_type index, float, Vector3& result) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
result = points[index+1] - points[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateDerivativeCatmullRom(index_type index, float t, Vector3& result) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
C_Evaluate_Derivative(&points[index - 1], t, s_catmullRomCoeffs, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::EvaluateDerivativeBezier3(index_type index, float t, Vector3& result) const
|
||||||
|
{
|
||||||
|
index *= 3u;
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
C_Evaluate_Derivative(&points[index], t, s_Bezier3Coeffs, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
float SplineBase::SegLengthLinear(index_type index) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
return (points[index] - points[index+1]).length();
|
||||||
|
}
|
||||||
|
|
||||||
|
float SplineBase::SegLengthCatmullRom(index_type index) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
|
||||||
|
Vector3 curPos, nextPos;
|
||||||
|
const Vector3* p = &points[index - 1];
|
||||||
|
curPos = nextPos = p[1];
|
||||||
|
|
||||||
|
index_type i = 1;
|
||||||
|
double length = 0;
|
||||||
|
while (i <= STEPS_PER_SEGMENT)
|
||||||
|
{
|
||||||
|
C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_catmullRomCoeffs, nextPos);
|
||||||
|
length += (nextPos - curPos).length();
|
||||||
|
curPos = nextPos;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SplineBase::SegLengthBezier3(index_type index) const
|
||||||
|
{
|
||||||
|
index *= 3u;
|
||||||
|
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
||||||
|
|
||||||
|
Vector3 curPos, nextPos;
|
||||||
|
const Vector3* p = &points[index];
|
||||||
|
|
||||||
|
C_Evaluate(p, 0.f, s_Bezier3Coeffs, nextPos);
|
||||||
curPos = nextPos;
|
curPos = nextPos;
|
||||||
++i;
|
|
||||||
|
index_type i = 1;
|
||||||
|
double length = 0;
|
||||||
|
while (i <= STEPS_PER_SEGMENT)
|
||||||
|
{
|
||||||
|
C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_Bezier3Coeffs, nextPos);
|
||||||
|
length += (nextPos - curPos).length();
|
||||||
|
curPos = nextPos;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
return length;
|
#pragma endregion
|
||||||
}
|
|
||||||
|
|
||||||
float SplineBase::SegLengthBezier3(index_type index) const
|
void SplineBase::init_spline(const Vector3* controls, index_type count, EvaluationMode m)
|
||||||
{
|
|
||||||
index *= 3u;
|
|
||||||
MANGOS_ASSERT(index >= index_lo && index < index_hi);
|
|
||||||
|
|
||||||
Vector3 curPos, nextPos;
|
|
||||||
const Vector3 * p = &points[index];
|
|
||||||
|
|
||||||
C_Evaluate(p, 0.f, s_Bezier3Coeffs, nextPos);
|
|
||||||
curPos = nextPos;
|
|
||||||
|
|
||||||
index_type i = 1;
|
|
||||||
double length = 0;
|
|
||||||
while (i <= STEPS_PER_SEGMENT)
|
|
||||||
{
|
{
|
||||||
C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_Bezier3Coeffs, nextPos);
|
m_mode = m;
|
||||||
length += (nextPos - curPos).length();
|
cyclic = false;
|
||||||
curPos = nextPos;
|
|
||||||
++i;
|
(this->*initializers[m_mode])(controls, count, cyclic, 0);
|
||||||
}
|
}
|
||||||
return length;
|
|
||||||
}
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
void SplineBase::init_spline(const Vector3 * controls, index_type count, EvaluationMode m)
|
void SplineBase::init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point)
|
||||||
{
|
|
||||||
m_mode = m;
|
|
||||||
cyclic = false;
|
|
||||||
|
|
||||||
(this->*initializers[m_mode])(controls, count, cyclic, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineBase::init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point)
|
|
||||||
{
|
|
||||||
m_mode = m;
|
|
||||||
cyclic = true;
|
|
||||||
|
|
||||||
(this->*initializers[m_mode])(controls, count, cyclic, cyclic_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineBase::InitLinear(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(count >= 2);
|
|
||||||
const int real_size = count + 1;
|
|
||||||
|
|
||||||
points.resize(real_size);
|
|
||||||
|
|
||||||
memcpy(&points[0],controls, sizeof(Vector3) * count);
|
|
||||||
|
|
||||||
// first and last two indexes are space for special 'virtual points'
|
|
||||||
// these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
|
|
||||||
if (cyclic)
|
|
||||||
points[count] = controls[cyclic_point];
|
|
||||||
else
|
|
||||||
points[count] = controls[count-1];
|
|
||||||
|
|
||||||
index_lo = 0;
|
|
||||||
index_hi = cyclic ? count : (count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
|
|
||||||
{
|
|
||||||
const int real_size = count + (cyclic ? (1+2) : (1+1));
|
|
||||||
|
|
||||||
points.resize(real_size);
|
|
||||||
|
|
||||||
int lo_index = 1;
|
|
||||||
int high_index = lo_index + count - 1;
|
|
||||||
|
|
||||||
memcpy(&points[lo_index],controls, sizeof(Vector3) * count);
|
|
||||||
|
|
||||||
// first and last two indexes are space for special 'virtual points'
|
|
||||||
// these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
|
|
||||||
if (cyclic)
|
|
||||||
{
|
{
|
||||||
if (cyclic_point == 0)
|
m_mode = m;
|
||||||
points[0] = controls[count-1];
|
cyclic = true;
|
||||||
|
|
||||||
|
(this->*initializers[m_mode])(controls, count, cyclic, cyclic_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineBase::InitLinear(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(count >= 2);
|
||||||
|
const int real_size = count + 1;
|
||||||
|
|
||||||
|
points.resize(real_size);
|
||||||
|
|
||||||
|
memcpy(&points[0],controls, sizeof(Vector3) * count);
|
||||||
|
|
||||||
|
// first and last two indexes are space for special 'virtual points'
|
||||||
|
// these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
|
||||||
|
if (cyclic)
|
||||||
|
points[count] = controls[cyclic_point];
|
||||||
else
|
else
|
||||||
points[0] = controls[0].lerp(controls[1], -1);
|
points[count] = controls[count-1];
|
||||||
|
|
||||||
points[high_index+1] = controls[cyclic_point];
|
index_lo = 0;
|
||||||
points[high_index+2] = controls[cyclic_point+1];
|
index_hi = cyclic ? count : (count - 1);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
|
||||||
{
|
{
|
||||||
points[0] = controls[0].lerp(controls[1], -1);
|
const int real_size = count + (cyclic ? (1+2) : (1+1));
|
||||||
points[high_index+1] = controls[count-1];
|
|
||||||
|
points.resize(real_size);
|
||||||
|
|
||||||
|
int lo_index = 1;
|
||||||
|
int high_index = lo_index + count - 1;
|
||||||
|
|
||||||
|
memcpy(&points[lo_index],controls, sizeof(Vector3) * count);
|
||||||
|
|
||||||
|
// first and last two indexes are space for special 'virtual points'
|
||||||
|
// these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
|
||||||
|
if (cyclic)
|
||||||
|
{
|
||||||
|
if (cyclic_point == 0)
|
||||||
|
points[0] = controls[count-1];
|
||||||
|
else
|
||||||
|
points[0] = controls[0].lerp(controls[1], -1);
|
||||||
|
|
||||||
|
points[high_index+1] = controls[cyclic_point];
|
||||||
|
points[high_index+2] = controls[cyclic_point+1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
points[0] = controls[0].lerp(controls[1], -1);
|
||||||
|
points[high_index+1] = controls[count-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
index_lo = lo_index;
|
||||||
|
index_hi = high_index + (cyclic ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
index_lo = lo_index;
|
void SplineBase::InitBezier3(const Vector3* controls, index_type count, bool /*cyclic*/, index_type /*cyclic_point*/)
|
||||||
index_hi = high_index + (cyclic ? 1 : 0);
|
{
|
||||||
}
|
index_type c = count / 3u * 3u;
|
||||||
|
index_type t = c / 3u;
|
||||||
|
|
||||||
void SplineBase::InitBezier3(const Vector3* controls, index_type count, bool /*cyclic*/, index_type /*cyclic_point*/)
|
points.resize(c);
|
||||||
{
|
memcpy(&points[0],controls, sizeof(Vector3) * c);
|
||||||
index_type c = count / 3u * 3u;
|
|
||||||
index_type t = c / 3u;
|
|
||||||
|
|
||||||
points.resize(c);
|
index_lo = 0;
|
||||||
memcpy(&points[0],controls, sizeof(Vector3) * c);
|
index_hi = t-1;
|
||||||
|
//mov_assert(points.size() % 3 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
index_lo = 0;
|
void SplineBase::clear()
|
||||||
index_hi = t-1;
|
{
|
||||||
//mov_assert(points.size() % 3 == 0);
|
index_lo = 0;
|
||||||
}
|
index_hi = 0;
|
||||||
|
points.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void SplineBase::clear()
|
std::string SplineBase::ToString() const
|
||||||
{
|
{
|
||||||
index_lo = 0;
|
std::stringstream str;
|
||||||
index_hi = 0;
|
const char* mode_str[ModesEnd] = {"Linear", "CatmullRom", "Bezier3", "Uninitialized"};
|
||||||
points.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string SplineBase::ToString() const
|
index_type count = this->points.size();
|
||||||
{
|
str << "mode: " << mode_str[mode()] << std::endl;
|
||||||
std::stringstream str;
|
str << "points count: " << count << std::endl;
|
||||||
const char * mode_str[ModesEnd] = {"Linear", "CatmullRom", "Bezier3", "Uninitialized"};
|
for (index_type i = 0; i < count; ++i)
|
||||||
|
str << "point " << i << " : " << points[i].toString() << std::endl;
|
||||||
|
|
||||||
index_type count = this->points.size();
|
return str.str();
|
||||||
str << "mode: " << mode_str[mode()] << std::endl;
|
}
|
||||||
str << "points count: " << count << std::endl;
|
|
||||||
for (index_type i = 0; i < count; ++i)
|
|
||||||
str << "point " << i << " : " << points[i].toString() << std::endl;
|
|
||||||
|
|
||||||
return str.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,184 +22,186 @@
|
||||||
#include "typedefs.h"
|
#include "typedefs.h"
|
||||||
#include <G3D/Vector3.h>
|
#include <G3D/Vector3.h>
|
||||||
|
|
||||||
namespace Movement {
|
namespace Movement
|
||||||
|
|
||||||
class SplineBase
|
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
typedef int index_type;
|
|
||||||
typedef std::vector<Vector3> ControlArray;
|
|
||||||
|
|
||||||
enum EvaluationMode
|
class SplineBase
|
||||||
{
|
{
|
||||||
ModeLinear,
|
public:
|
||||||
ModeCatmullrom,
|
typedef int index_type;
|
||||||
ModeBezier3_Unused,
|
typedef std::vector<Vector3> ControlArray;
|
||||||
UninitializedMode,
|
|
||||||
ModesEnd
|
enum EvaluationMode
|
||||||
|
{
|
||||||
|
ModeLinear,
|
||||||
|
ModeCatmullrom,
|
||||||
|
ModeBezier3_Unused,
|
||||||
|
UninitializedMode,
|
||||||
|
ModesEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ControlArray points;
|
||||||
|
|
||||||
|
index_type index_lo;
|
||||||
|
index_type index_hi;
|
||||||
|
|
||||||
|
uint8 m_mode;
|
||||||
|
bool cyclic;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
// could be modified, affects segment length evaluation precision
|
||||||
|
// lesser value saves more performance in cost of lover precision
|
||||||
|
// minimal value is 1
|
||||||
|
// client's value is 20, blizzs use 2-3 steps to compute length
|
||||||
|
STEPS_PER_SEGMENT = 3,
|
||||||
|
};
|
||||||
|
static_assert(STEPS_PER_SEGMENT > 0, "shouldn't be lesser than 1");
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void EvaluateLinear(index_type, float, Vector3&) const;
|
||||||
|
void EvaluateCatmullRom(index_type, float, Vector3&) const;
|
||||||
|
void EvaluateBezier3(index_type, float, Vector3&) const;
|
||||||
|
typedef void (SplineBase::*EvaluationMethtod)(index_type,float,Vector3&) const;
|
||||||
|
static EvaluationMethtod evaluators[ModesEnd];
|
||||||
|
|
||||||
|
void EvaluateDerivativeLinear(index_type, float, Vector3&) const;
|
||||||
|
void EvaluateDerivativeCatmullRom(index_type, float, Vector3&) const;
|
||||||
|
void EvaluateDerivativeBezier3(index_type, float, Vector3&) const;
|
||||||
|
static EvaluationMethtod derivative_evaluators[ModesEnd];
|
||||||
|
|
||||||
|
float SegLengthLinear(index_type) const;
|
||||||
|
float SegLengthCatmullRom(index_type) const;
|
||||||
|
float SegLengthBezier3(index_type) const;
|
||||||
|
typedef float(SplineBase::*SegLenghtMethtod)(index_type) const;
|
||||||
|
static SegLenghtMethtod seglengths[ModesEnd];
|
||||||
|
|
||||||
|
void InitLinear(const Vector3*, index_type, bool, index_type);
|
||||||
|
void InitCatmullRom(const Vector3*, index_type, bool, index_type);
|
||||||
|
void InitBezier3(const Vector3*, index_type, bool, index_type);
|
||||||
|
typedef void (SplineBase::*InitMethtod)(const Vector3*, index_type, bool, index_type);
|
||||||
|
static InitMethtod initializers[ModesEnd];
|
||||||
|
|
||||||
|
void UninitializedSpline() const { MANGOS_ASSERT(false);}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit SplineBase() : index_lo(0), index_hi(0), m_mode(UninitializedMode), cyclic(false) {}
|
||||||
|
|
||||||
|
/** Caclulates the position for given segment Idx, and percent of segment length t
|
||||||
|
@param t - percent of segment length, assumes that t in range [0, 1]
|
||||||
|
@param Idx - spline segment index, should be in range [first, last)
|
||||||
|
*/
|
||||||
|
void evaluate_percent(index_type Idx, float u, Vector3& c) const {(this->*evaluators[m_mode])(Idx,u,c);}
|
||||||
|
|
||||||
|
/** Caclulates derivation in index Idx, and percent of segment length t
|
||||||
|
@param Idx - spline segment index, should be in range [first, last)
|
||||||
|
@param t - percent of spline segment length, assumes that t in range [0, 1]
|
||||||
|
*/
|
||||||
|
void evaluate_derivative(index_type Idx, float u, Vector3& hermite) const {(this->*derivative_evaluators[m_mode])(Idx,u,hermite);}
|
||||||
|
|
||||||
|
/** Bounds for spline indexes. All indexes should be in range [first, last). */
|
||||||
|
index_type first() const { return index_lo;}
|
||||||
|
index_type last() const { return index_hi;}
|
||||||
|
|
||||||
|
bool empty() const { return index_lo == index_hi;}
|
||||||
|
EvaluationMode mode() const { return (EvaluationMode)m_mode;}
|
||||||
|
bool isCyclic() const { return cyclic;}
|
||||||
|
|
||||||
|
const ControlArray& getPoints() const { return points;}
|
||||||
|
index_type getPointCount() const { return points.size();}
|
||||||
|
const Vector3& getPoint(index_type i) const { return points[i];}
|
||||||
|
|
||||||
|
/** Initializes spline. Don't call other methods while spline not initialized. */
|
||||||
|
void init_spline(const Vector3* controls, index_type count, EvaluationMode m);
|
||||||
|
void init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point);
|
||||||
|
|
||||||
|
/** As i can see there are a lot of ways how spline can be initialized
|
||||||
|
would be no harm to have some custom initializers. */
|
||||||
|
template<class Init> inline void init_spline(Init& initializer)
|
||||||
|
{
|
||||||
|
initializer(m_mode,cyclic,points,index_lo,index_hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/** Calculates distance between [i; i+1] points, assumes that index i is in bounds. */
|
||||||
|
float SegLength(index_type i) const { return (this->*seglengths[m_mode])(i);}
|
||||||
|
|
||||||
|
std::string ToString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
template<typename length_type>
|
||||||
ControlArray points;
|
class Spline : public SplineBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef length_type LengthType;
|
||||||
|
typedef std::vector<length_type> LengthArray;
|
||||||
|
protected:
|
||||||
|
|
||||||
index_type index_lo;
|
LengthArray lengths;
|
||||||
index_type index_hi;
|
|
||||||
|
|
||||||
uint8 m_mode;
|
index_type computeIndexInBounds(length_type length) const;
|
||||||
bool cyclic;
|
public:
|
||||||
|
|
||||||
enum{
|
explicit Spline() {}
|
||||||
// could be modified, affects segment length evaluation precision
|
|
||||||
// lesser value saves more performance in cost of lover precision
|
/** Calculates the position for given t
|
||||||
// minimal value is 1
|
@param t - percent of spline's length, assumes that t in range [0, 1]. */
|
||||||
// client's value is 20, blizzs use 2-3 steps to compute length
|
void evaluate_percent(float t, Vector3& c) const;
|
||||||
STEPS_PER_SEGMENT = 3,
|
|
||||||
|
/** Calculates derivation for given t
|
||||||
|
@param t - percent of spline's length, assumes that t in range [0, 1]. */
|
||||||
|
void evaluate_derivative(float t, Vector3& hermite) const;
|
||||||
|
|
||||||
|
/** Calculates the position for given segment Idx, and percent of segment length t
|
||||||
|
@param t = partial_segment_length / whole_segment_length
|
||||||
|
@param Idx - spline segment index, should be in range [first, last). */
|
||||||
|
void evaluate_percent(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_percent(Idx,u,c);}
|
||||||
|
|
||||||
|
/** Caclulates derivation for index Idx, and percent of segment length t
|
||||||
|
@param Idx - spline segment index, should be in range [first, last)
|
||||||
|
@param t - percent of spline segment length, assumes that t in range [0, 1]. */
|
||||||
|
void evaluate_derivative(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_derivative(Idx,u,c);}
|
||||||
|
|
||||||
|
// Assumes that t in range [0, 1]
|
||||||
|
index_type computeIndexInBounds(float t) const;
|
||||||
|
void computeIndex(float t, index_type& out_idx, float& out_u) const;
|
||||||
|
|
||||||
|
/** Initializes spline. Don't call other methods while spline not initialized. */
|
||||||
|
void init_spline(const Vector3* controls, index_type count, EvaluationMode m) { SplineBase::init_spline(controls,count,m);}
|
||||||
|
void init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point) { SplineBase::init_cyclic_spline(controls,count,m,cyclic_point);}
|
||||||
|
|
||||||
|
/** Initializes lengths with SplineBase::SegLength method. */
|
||||||
|
void initLengths();
|
||||||
|
|
||||||
|
/** Initializes lengths in some custom way
|
||||||
|
Note that value returned by cacher must be greater or equal to previous value. */
|
||||||
|
template<class T> inline void initLengths(T& cacher)
|
||||||
|
{
|
||||||
|
index_type i = index_lo;
|
||||||
|
lengths.resize(index_hi+1);
|
||||||
|
length_type prev_length = 0, new_length = 0;
|
||||||
|
while (i < index_hi)
|
||||||
|
{
|
||||||
|
new_length = cacher(*this, i);
|
||||||
|
lengths[++i] = new_length;
|
||||||
|
|
||||||
|
MANGOS_ASSERT(prev_length <= new_length);
|
||||||
|
prev_length = new_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns length of the whole spline. */
|
||||||
|
length_type length() const { return lengths[index_hi];}
|
||||||
|
/** Returns length between given nodes. */
|
||||||
|
length_type length(index_type first, index_type last) const { return lengths[last]-lengths[first];}
|
||||||
|
length_type length(index_type Idx) const { return lengths[Idx];}
|
||||||
|
|
||||||
|
void set_length(index_type i, length_type length) { lengths[i] = length;}
|
||||||
|
void clear();
|
||||||
};
|
};
|
||||||
static_assert(STEPS_PER_SEGMENT > 0, "shouldn't be lesser than 1");
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void EvaluateLinear(index_type, float, Vector3&) const;
|
|
||||||
void EvaluateCatmullRom(index_type, float, Vector3&) const;
|
|
||||||
void EvaluateBezier3(index_type, float, Vector3&) const;
|
|
||||||
typedef void (SplineBase::*EvaluationMethtod)(index_type,float,Vector3&) const;
|
|
||||||
static EvaluationMethtod evaluators[ModesEnd];
|
|
||||||
|
|
||||||
void EvaluateDerivativeLinear(index_type, float, Vector3&) const;
|
|
||||||
void EvaluateDerivativeCatmullRom(index_type, float, Vector3&) const;
|
|
||||||
void EvaluateDerivativeBezier3(index_type, float, Vector3&) const;
|
|
||||||
static EvaluationMethtod derivative_evaluators[ModesEnd];
|
|
||||||
|
|
||||||
float SegLengthLinear(index_type) const;
|
|
||||||
float SegLengthCatmullRom(index_type) const;
|
|
||||||
float SegLengthBezier3(index_type) const;
|
|
||||||
typedef float (SplineBase::*SegLenghtMethtod)(index_type) const;
|
|
||||||
static SegLenghtMethtod seglengths[ModesEnd];
|
|
||||||
|
|
||||||
void InitLinear(const Vector3*, index_type, bool, index_type);
|
|
||||||
void InitCatmullRom(const Vector3*, index_type, bool, index_type);
|
|
||||||
void InitBezier3(const Vector3*, index_type, bool, index_type);
|
|
||||||
typedef void (SplineBase::*InitMethtod)(const Vector3*, index_type, bool, index_type);
|
|
||||||
static InitMethtod initializers[ModesEnd];
|
|
||||||
|
|
||||||
void UninitializedSpline() const { MANGOS_ASSERT(false);}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit SplineBase() : index_lo(0), index_hi(0), m_mode(UninitializedMode), cyclic(false) {}
|
|
||||||
|
|
||||||
/** Caclulates the position for given segment Idx, and percent of segment length t
|
|
||||||
@param t - percent of segment length, assumes that t in range [0, 1]
|
|
||||||
@param Idx - spline segment index, should be in range [first, last)
|
|
||||||
*/
|
|
||||||
void evaluate_percent(index_type Idx, float u, Vector3& c) const {(this->*evaluators[m_mode])(Idx,u,c);}
|
|
||||||
|
|
||||||
/** Caclulates derivation in index Idx, and percent of segment length t
|
|
||||||
@param Idx - spline segment index, should be in range [first, last)
|
|
||||||
@param t - percent of spline segment length, assumes that t in range [0, 1]
|
|
||||||
*/
|
|
||||||
void evaluate_derivative(index_type Idx, float u, Vector3& hermite) const {(this->*derivative_evaluators[m_mode])(Idx,u,hermite);}
|
|
||||||
|
|
||||||
/** Bounds for spline indexes. All indexes should be in range [first, last). */
|
|
||||||
index_type first() const { return index_lo;}
|
|
||||||
index_type last() const { return index_hi;}
|
|
||||||
|
|
||||||
bool empty() const { return index_lo == index_hi;}
|
|
||||||
EvaluationMode mode() const { return (EvaluationMode)m_mode;}
|
|
||||||
bool isCyclic() const { return cyclic;}
|
|
||||||
|
|
||||||
const ControlArray& getPoints() const { return points;}
|
|
||||||
index_type getPointCount() const { return points.size();}
|
|
||||||
const Vector3& getPoint(index_type i) const { return points[i];}
|
|
||||||
|
|
||||||
/** Initializes spline. Don't call other methods while spline not initialized. */
|
|
||||||
void init_spline(const Vector3 * controls, index_type count, EvaluationMode m);
|
|
||||||
void init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point);
|
|
||||||
|
|
||||||
/** As i can see there are a lot of ways how spline can be initialized
|
|
||||||
would be no harm to have some custom initializers. */
|
|
||||||
template<class Init> inline void init_spline(Init& initializer)
|
|
||||||
{
|
|
||||||
initializer(m_mode,cyclic,points,index_lo,index_hi);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
/** Calculates distance between [i; i+1] points, assumes that index i is in bounds. */
|
|
||||||
float SegLength(index_type i) const { return (this->*seglengths[m_mode])(i);}
|
|
||||||
|
|
||||||
std::string ToString() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename length_type>
|
|
||||||
class Spline : public SplineBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef length_type LengthType;
|
|
||||||
typedef std::vector<length_type> LengthArray;
|
|
||||||
protected:
|
|
||||||
|
|
||||||
LengthArray lengths;
|
|
||||||
|
|
||||||
index_type computeIndexInBounds(length_type length) const;
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit Spline(){}
|
|
||||||
|
|
||||||
/** Calculates the position for given t
|
|
||||||
@param t - percent of spline's length, assumes that t in range [0, 1]. */
|
|
||||||
void evaluate_percent(float t, Vector3 & c) const;
|
|
||||||
|
|
||||||
/** Calculates derivation for given t
|
|
||||||
@param t - percent of spline's length, assumes that t in range [0, 1]. */
|
|
||||||
void evaluate_derivative(float t, Vector3& hermite) const;
|
|
||||||
|
|
||||||
/** Calculates the position for given segment Idx, and percent of segment length t
|
|
||||||
@param t = partial_segment_length / whole_segment_length
|
|
||||||
@param Idx - spline segment index, should be in range [first, last). */
|
|
||||||
void evaluate_percent(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_percent(Idx,u,c);}
|
|
||||||
|
|
||||||
/** Caclulates derivation for index Idx, and percent of segment length t
|
|
||||||
@param Idx - spline segment index, should be in range [first, last)
|
|
||||||
@param t - percent of spline segment length, assumes that t in range [0, 1]. */
|
|
||||||
void evaluate_derivative(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_derivative(Idx,u,c);}
|
|
||||||
|
|
||||||
// Assumes that t in range [0, 1]
|
|
||||||
index_type computeIndexInBounds(float t) const;
|
|
||||||
void computeIndex(float t, index_type& out_idx, float& out_u) const;
|
|
||||||
|
|
||||||
/** Initializes spline. Don't call other methods while spline not initialized. */
|
|
||||||
void init_spline(const Vector3 * controls, index_type count, EvaluationMode m) { SplineBase::init_spline(controls,count,m);}
|
|
||||||
void init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point) { SplineBase::init_cyclic_spline(controls,count,m,cyclic_point);}
|
|
||||||
|
|
||||||
/** Initializes lengths with SplineBase::SegLength method. */
|
|
||||||
void initLengths();
|
|
||||||
|
|
||||||
/** Initializes lengths in some custom way
|
|
||||||
Note that value returned by cacher must be greater or equal to previous value. */
|
|
||||||
template<class T> inline void initLengths(T& cacher)
|
|
||||||
{
|
|
||||||
index_type i = index_lo;
|
|
||||||
lengths.resize(index_hi+1);
|
|
||||||
length_type prev_length = 0, new_length = 0;
|
|
||||||
while(i < index_hi)
|
|
||||||
{
|
|
||||||
new_length = cacher(*this, i);
|
|
||||||
lengths[++i] = new_length;
|
|
||||||
|
|
||||||
MANGOS_ASSERT(prev_length <= new_length);
|
|
||||||
prev_length = new_length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns length of the whole spline. */
|
|
||||||
length_type length() const { return lengths[index_hi];}
|
|
||||||
/** Returns length between given nodes. */
|
|
||||||
length_type length(index_type first, index_type last) const { return lengths[last]-lengths[first];}
|
|
||||||
length_type length(index_type Idx) const { return lengths[Idx];}
|
|
||||||
|
|
||||||
void set_length(index_type i, length_type length) { lengths[i] = length;}
|
|
||||||
void clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,80 +18,80 @@
|
||||||
|
|
||||||
namespace Movement
|
namespace Movement
|
||||||
{
|
{
|
||||||
template<typename length_type> void Spline<length_type>::evaluate_percent( float t, Vector3 & c ) const
|
template<typename length_type> void Spline<length_type>::evaluate_percent(float t, Vector3& c) const
|
||||||
{
|
|
||||||
index_type Index;
|
|
||||||
float u;
|
|
||||||
computeIndex(t, Index, u);
|
|
||||||
evaluate_percent(Index, u, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename length_type> void Spline<length_type>::evaluate_derivative(float t, Vector3& hermite) const
|
|
||||||
{
|
|
||||||
index_type Index;
|
|
||||||
float u;
|
|
||||||
computeIndex(t, Index, u);
|
|
||||||
evaluate_derivative(Index, u, hermite);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename length_type> SplineBase::index_type Spline<length_type>::computeIndexInBounds(length_type length_) const
|
|
||||||
{
|
|
||||||
// Temporary disabled: causes infinite loop with t = 1.f
|
|
||||||
/*
|
|
||||||
index_type hi = index_hi;
|
|
||||||
index_type lo = index_lo;
|
|
||||||
|
|
||||||
index_type i = lo + (float)(hi - lo) * t;
|
|
||||||
|
|
||||||
while ((lengths[i] > length) || (lengths[i + 1] <= length))
|
|
||||||
{
|
{
|
||||||
if (lengths[i] > length)
|
index_type Index;
|
||||||
hi = i - 1; // too big
|
float u;
|
||||||
else if (lengths[i + 1] <= length)
|
computeIndex(t, Index, u);
|
||||||
lo = i + 1; // too small
|
evaluate_percent(Index, u, c);
|
||||||
|
|
||||||
i = (hi + lo) / 2;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
index_type i = index_lo;
|
|
||||||
index_type N = index_hi;
|
|
||||||
while (i+1 < N && lengths[i+1] < length_)
|
|
||||||
++i;
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename length_type> void Spline<length_type>::computeIndex(float t, index_type& index, float& u) const
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(t >= 0.f && t <= 1.f);
|
|
||||||
length_type length_ = t * length();
|
|
||||||
index = computeIndexInBounds(length_);
|
|
||||||
MANGOS_ASSERT(index < index_hi);
|
|
||||||
u = (length_ - length(index)) / (float)length(index, index+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename length_type> SplineBase::index_type Spline<length_type>::computeIndexInBounds( float t ) const
|
|
||||||
{
|
|
||||||
MANGOS_ASSERT(t >= 0.f && t <= 1.f);
|
|
||||||
return computeIndexInBounds(t * length());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename length_type> void Spline<length_type>::initLengths()
|
|
||||||
{
|
|
||||||
index_type i = index_lo;
|
|
||||||
length_type length = 0;
|
|
||||||
lengths.resize(index_hi+1);
|
|
||||||
while(i < index_hi )
|
|
||||||
{
|
|
||||||
length += SegLength(i);
|
|
||||||
lengths[++i] = length;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename length_type> void Spline<length_type>::clear()
|
template<typename length_type> void Spline<length_type>::evaluate_derivative(float t, Vector3& hermite) const
|
||||||
{
|
{
|
||||||
SplineBase::clear();
|
index_type Index;
|
||||||
lengths.clear();
|
float u;
|
||||||
}
|
computeIndex(t, Index, u);
|
||||||
|
evaluate_derivative(Index, u, hermite);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> SplineBase::index_type Spline<length_type>::computeIndexInBounds(length_type length_) const
|
||||||
|
{
|
||||||
|
// Temporary disabled: causes infinite loop with t = 1.f
|
||||||
|
/*
|
||||||
|
index_type hi = index_hi;
|
||||||
|
index_type lo = index_lo;
|
||||||
|
|
||||||
|
index_type i = lo + (float)(hi - lo) * t;
|
||||||
|
|
||||||
|
while ((lengths[i] > length) || (lengths[i + 1] <= length))
|
||||||
|
{
|
||||||
|
if (lengths[i] > length)
|
||||||
|
hi = i - 1; // too big
|
||||||
|
else if (lengths[i + 1] <= length)
|
||||||
|
lo = i + 1; // too small
|
||||||
|
|
||||||
|
i = (hi + lo) / 2;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
index_type i = index_lo;
|
||||||
|
index_type N = index_hi;
|
||||||
|
while (i+1 < N && lengths[i+1] < length_)
|
||||||
|
++i;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> void Spline<length_type>::computeIndex(float t, index_type& index, float& u) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(t >= 0.f && t <= 1.f);
|
||||||
|
length_type length_ = t * length();
|
||||||
|
index = computeIndexInBounds(length_);
|
||||||
|
MANGOS_ASSERT(index < index_hi);
|
||||||
|
u = (length_ - length(index)) / (float)length(index, index+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> SplineBase::index_type Spline<length_type>::computeIndexInBounds(float t) const
|
||||||
|
{
|
||||||
|
MANGOS_ASSERT(t >= 0.f && t <= 1.f);
|
||||||
|
return computeIndexInBounds(t * length());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> void Spline<length_type>::initLengths()
|
||||||
|
{
|
||||||
|
index_type i = index_lo;
|
||||||
|
length_type length = 0;
|
||||||
|
lengths.resize(index_hi+1);
|
||||||
|
while (i < index_hi)
|
||||||
|
{
|
||||||
|
length += SegLength(i);
|
||||||
|
lengths[++i] = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename length_type> void Spline<length_type>::clear()
|
||||||
|
{
|
||||||
|
SplineBase::clear();
|
||||||
|
lengths.clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,31 +45,31 @@ namespace Movement
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef static_assert
|
#ifndef static_assert
|
||||||
#define CONCAT(x, y) CONCAT1 (x, y)
|
#define CONCAT(x, y) CONCAT1 (x, y)
|
||||||
#define CONCAT1(x, y) x##y
|
#define CONCAT1(x, y) x##y
|
||||||
#define static_assert(expr, msg) typedef char CONCAT(static_assert_failed_at_line_, __LINE__) [(expr) ? 1 : -1]
|
#define static_assert(expr, msg) typedef char CONCAT(static_assert_failed_at_line_, __LINE__) [(expr) ? 1 : -1]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<class T, T limit>
|
template<class T, T limit>
|
||||||
class counter
|
class counter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
counter() { init();}
|
counter() { init();}
|
||||||
|
|
||||||
void Increase()
|
void Increase()
|
||||||
{
|
{
|
||||||
if (m_counter == limit)
|
if (m_counter == limit)
|
||||||
init();
|
init();
|
||||||
else
|
else
|
||||||
++m_counter;
|
++m_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
T NewId() { Increase(); return m_counter;}
|
T NewId() { Increase(); return m_counter;}
|
||||||
T getCurrent() const { return m_counter;}
|
T getCurrent() const { return m_counter;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init() { m_counter = 0; }
|
void init() { m_counter = 0; }
|
||||||
T m_counter;
|
T m_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef counter<uint32, 0xFFFFFFFF> UInt32Counter;
|
typedef counter<uint32, 0xFFFFFFFF> UInt32Counter;
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ namespace Movement
|
||||||
float terminalVelocity = 60.148003f;
|
float terminalVelocity = 60.148003f;
|
||||||
float terminalSavefallVelocity = 7.f;
|
float terminalSavefallVelocity = 7.f;
|
||||||
|
|
||||||
const float terminal_length = float(terminalVelocity * terminalVelocity) / (2.f * gravity);
|
const float terminal_length = float(terminalVelocity* terminalVelocity) / (2.f* gravity);
|
||||||
const float terminal_savefall_length = (terminalSavefallVelocity * terminalSavefallVelocity) / (2.f * gravity);
|
const float terminal_savefall_length = (terminalSavefallVelocity* terminalSavefallVelocity) / (2.f* gravity);
|
||||||
const float terminalFallTime = float(terminalVelocity/gravity); // the time that needed to reach terminalVelocity
|
const float terminalFallTime = float(terminalVelocity/gravity); // the time that needed to reach terminalVelocity
|
||||||
|
|
||||||
float computeFallTime(float path_length, bool isSafeFall)
|
float computeFallTime(float path_length, bool isSafeFall)
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Movement
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
|
||||||
float time;
|
float time;
|
||||||
if ( isSafeFall )
|
if (isSafeFall)
|
||||||
{
|
{
|
||||||
if (path_length >= terminal_savefall_length)
|
if (path_length >= terminal_savefall_length)
|
||||||
time = (path_length - terminal_savefall_length)/terminalSavefallVelocity + terminalSavefallVelocity/gravity;
|
time = (path_length - terminal_savefall_length)/terminalSavefallVelocity + terminalSavefallVelocity/gravity;
|
||||||
|
|
@ -61,20 +61,20 @@ namespace Movement
|
||||||
float termVel;
|
float termVel;
|
||||||
float result;
|
float result;
|
||||||
|
|
||||||
if ( isSafeFall )
|
if (isSafeFall)
|
||||||
termVel = terminalSavefallVelocity;
|
termVel = terminalSavefallVelocity;
|
||||||
else
|
else
|
||||||
termVel = terminalVelocity;
|
termVel = terminalVelocity;
|
||||||
|
|
||||||
if ( start_velocity > termVel )
|
if (start_velocity > termVel)
|
||||||
start_velocity = termVel;
|
start_velocity = termVel;
|
||||||
|
|
||||||
float terminal_time = terminalFallTime - start_velocity / gravity; // the time that needed to reach terminalVelocity
|
float terminal_time = terminalFallTime - start_velocity / gravity; // the time that needed to reach terminalVelocity
|
||||||
|
|
||||||
if ( t_passed > terminal_time )
|
if (t_passed > terminal_time)
|
||||||
{
|
{
|
||||||
result = terminalVelocity*(t_passed - terminal_time) +
|
result = terminalVelocity*(t_passed - terminal_time) +
|
||||||
start_velocity*terminal_time + gravity*terminal_time*terminal_time*0.5f;
|
start_velocity*terminal_time + gravity*terminal_time*terminal_time*0.5f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = t_passed * (start_velocity + t_passed * gravity * 0.5f);
|
result = t_passed * (start_velocity + t_passed * gravity * 0.5f);
|
||||||
|
|
@ -98,95 +98,95 @@ namespace Movement
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define STR(x) #x
|
#define STR(x) #x
|
||||||
|
|
||||||
const char * g_MovementFlag_names[]=
|
const char* g_MovementFlag_names[]=
|
||||||
{
|
{
|
||||||
STR(Forward ),// 0x00000001,
|
STR(Forward), // 0x00000001,
|
||||||
STR(Backward ),// 0x00000002,
|
STR(Backward), // 0x00000002,
|
||||||
STR(Strafe_Left ),// 0x00000004,
|
STR(Strafe_Left), // 0x00000004,
|
||||||
STR(Strafe_Right ),// 0x00000008,
|
STR(Strafe_Right), // 0x00000008,
|
||||||
STR(Turn_Left ),// 0x00000010,
|
STR(Turn_Left), // 0x00000010,
|
||||||
STR(Turn_Right ),// 0x00000020,
|
STR(Turn_Right), // 0x00000020,
|
||||||
STR(Pitch_Up ),// 0x00000040,
|
STR(Pitch_Up), // 0x00000040,
|
||||||
STR(Pitch_Down ),// 0x00000080,
|
STR(Pitch_Down), // 0x00000080,
|
||||||
|
|
||||||
STR(Walk ),// 0x00000100, // Walking
|
STR(Walk), // 0x00000100, // Walking
|
||||||
STR(Ontransport ),// 0x00000200,
|
STR(Ontransport), // 0x00000200,
|
||||||
STR(Levitation ),// 0x00000400,
|
STR(Levitation), // 0x00000400,
|
||||||
STR(Root ),// 0x00000800,
|
STR(Root), // 0x00000800,
|
||||||
STR(Falling ),// 0x00001000,
|
STR(Falling), // 0x00001000,
|
||||||
STR(Fallingfar ),// 0x00002000,
|
STR(Fallingfar), // 0x00002000,
|
||||||
STR(Pendingstop ),// 0x00004000,
|
STR(Pendingstop), // 0x00004000,
|
||||||
STR(PendingSTRafestop ),// 0x00008000,
|
STR(PendingSTRafestop), // 0x00008000,
|
||||||
STR(Pendingforward ),// 0x00010000,
|
STR(Pendingforward), // 0x00010000,
|
||||||
STR(Pendingbackward ),// 0x00020000,
|
STR(Pendingbackward), // 0x00020000,
|
||||||
STR(PendingSTRafeleft ),// 0x00040000,
|
STR(PendingSTRafeleft), // 0x00040000,
|
||||||
STR(PendingSTRaferight ),// 0x00080000,
|
STR(PendingSTRaferight), // 0x00080000,
|
||||||
STR(Pendingroot ),// 0x00100000,
|
STR(Pendingroot), // 0x00100000,
|
||||||
STR(Swimming ),// 0x00200000, // Appears With Fly Flag Also
|
STR(Swimming), // 0x00200000, // Appears With Fly Flag Also
|
||||||
STR(Ascending ),// 0x00400000, // Swim Up Also
|
STR(Ascending), // 0x00400000, // Swim Up Also
|
||||||
STR(Descending ),// 0x00800000, // Swim Down Also
|
STR(Descending), // 0x00800000, // Swim Down Also
|
||||||
STR(Can_Fly ),// 0x01000000, // Can Fly In 3.3?
|
STR(Can_Fly), // 0x01000000, // Can Fly In 3.3?
|
||||||
STR(Flying ),// 0x02000000, // Actual Flying Mode
|
STR(Flying), // 0x02000000, // Actual Flying Mode
|
||||||
STR(Spline_Elevation ),// 0x04000000, // Used For Flight Paths
|
STR(Spline_Elevation), // 0x04000000, // Used For Flight Paths
|
||||||
STR(Spline_Enabled ),// 0x08000000, // Used For Flight Paths
|
STR(Spline_Enabled), // 0x08000000, // Used For Flight Paths
|
||||||
STR(Waterwalking ),// 0x10000000, // Prevent Unit From Falling Through Water
|
STR(Waterwalking), // 0x10000000, // Prevent Unit From Falling Through Water
|
||||||
STR(Safe_Fall ),// 0x20000000, // Active Rogue Safe Fall Spell (Passive)
|
STR(Safe_Fall), // 0x20000000, // Active Rogue Safe Fall Spell (Passive)
|
||||||
STR(Hover ),// 0x40000000
|
STR(Hover), // 0x40000000
|
||||||
STR(Unknown13 ),// 0x80000000
|
STR(Unknown13), // 0x80000000
|
||||||
STR(Unk1 ),
|
STR(Unk1),
|
||||||
STR(Unk2 ),
|
STR(Unk2),
|
||||||
STR(Unk3 ),
|
STR(Unk3),
|
||||||
STR(Fullspeedturning ),
|
STR(Fullspeedturning),
|
||||||
STR(Fullspeedpitching ),
|
STR(Fullspeedpitching),
|
||||||
STR(Allow_Pitching ),
|
STR(Allow_Pitching),
|
||||||
STR(Unk4 ),
|
STR(Unk4),
|
||||||
STR(Unk5 ),
|
STR(Unk5),
|
||||||
STR(Unk6 ),
|
STR(Unk6),
|
||||||
STR(Unk7 ),
|
STR(Unk7),
|
||||||
STR(Interp_Move ),
|
STR(Interp_Move),
|
||||||
STR(Interp_Turning ),
|
STR(Interp_Turning),
|
||||||
STR(Interp_Pitching ),
|
STR(Interp_Pitching),
|
||||||
STR(Unk8 ),
|
STR(Unk8),
|
||||||
STR(Unk9 ),
|
STR(Unk9),
|
||||||
STR(Unk10 ),
|
STR(Unk10),
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * g_SplineFlag_names[32]=
|
const char* g_SplineFlag_names[32]=
|
||||||
{
|
{
|
||||||
STR(AnimBit1 ),// 0x00000001,
|
STR(AnimBit1), // 0x00000001,
|
||||||
STR(AnimBit2 ),// 0x00000002,
|
STR(AnimBit2), // 0x00000002,
|
||||||
STR(AnimBit3 ),// 0x00000004,
|
STR(AnimBit3), // 0x00000004,
|
||||||
STR(AnimBit4 ),// 0x00000008,
|
STR(AnimBit4), // 0x00000008,
|
||||||
STR(AnimBit5 ),// 0x00000010,
|
STR(AnimBit5), // 0x00000010,
|
||||||
STR(AnimBit6 ),// 0x00000020,
|
STR(AnimBit6), // 0x00000020,
|
||||||
STR(AnimBit7 ),// 0x00000040,
|
STR(AnimBit7), // 0x00000040,
|
||||||
STR(AnimBit8 ),// 0x00000080,
|
STR(AnimBit8), // 0x00000080,
|
||||||
STR(Done ),// 0x00000100,
|
STR(Done), // 0x00000100,
|
||||||
STR(Falling ),// 0x00000200, // Not Compartible With Trajectory Movement
|
STR(Falling), // 0x00000200, // Not Compartible With Trajectory Movement
|
||||||
STR(No_Spline ),// 0x00000400,
|
STR(No_Spline), // 0x00000400,
|
||||||
STR(Trajectory ),// 0x00000800, // Not Compartible With Fall Movement
|
STR(Trajectory), // 0x00000800, // Not Compartible With Fall Movement
|
||||||
STR(Walkmode ),// 0x00001000,
|
STR(Walkmode), // 0x00001000,
|
||||||
STR(Flying ),// 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
|
STR(Flying), // 0x00002000, // Smooth Movement(Catmullrom Interpolation Mode), Flying Animation
|
||||||
STR(Knockback ),// 0x00004000, // Model Orientation Fixed
|
STR(Knockback), // 0x00004000, // Model Orientation Fixed
|
||||||
STR(Final_Point ),// 0x00008000,
|
STR(Final_Point), // 0x00008000,
|
||||||
STR(Final_Target ),// 0x00010000,
|
STR(Final_Target), // 0x00010000,
|
||||||
STR(Final_Angle ),// 0x00020000,
|
STR(Final_Angle), // 0x00020000,
|
||||||
STR(Catmullrom ),// 0x00040000, // Used Catmullrom Interpolation Mode
|
STR(Catmullrom), // 0x00040000, // Used Catmullrom Interpolation Mode
|
||||||
STR(Cyclic ),// 0x00080000, // Movement By Cycled Spline
|
STR(Cyclic), // 0x00080000, // Movement By Cycled Spline
|
||||||
STR(Enter_Cycle ),// 0x00100000, // Everytime Appears With Cyclic Flag In Monster Move Packet
|
STR(Enter_Cycle), // 0x00100000, // Everytime Appears With Cyclic Flag In Monster Move Packet
|
||||||
STR(Animation ),// 0x00200000, // Animationid (0...3), Uint32 Time, Not Compartible With Trajectory And Fall Movement
|
STR(Animation), // 0x00200000, // Animationid (0...3), Uint32 Time, Not Compartible With Trajectory And Fall Movement
|
||||||
STR(Unknown4 ),// 0x00400000, // Disables Movement By Path
|
STR(Unknown4), // 0x00400000, // Disables Movement By Path
|
||||||
STR(Unknown5 ),// 0x00800000,
|
STR(Unknown5), // 0x00800000,
|
||||||
STR(Unknown6 ),// 0x01000000,
|
STR(Unknown6), // 0x01000000,
|
||||||
STR(Unknown7 ),// 0x02000000,
|
STR(Unknown7), // 0x02000000,
|
||||||
STR(Unknown8 ),// 0x04000000,
|
STR(Unknown8), // 0x04000000,
|
||||||
STR(OrientationInversed ),// 0x08000000, // Appears With Runmode Flag, Nodes ),// 1, Handles Orientation
|
STR(OrientationInversed), // 0x08000000, // Appears With Runmode Flag, Nodes ),// 1, Handles Orientation
|
||||||
STR(Unknown10 ),// 0x10000000,
|
STR(Unknown10), // 0x10000000,
|
||||||
STR(Unknown11 ),// 0x20000000,
|
STR(Unknown11), // 0x20000000,
|
||||||
STR(Unknown12 ),// 0x40000000,
|
STR(Unknown12), // 0x40000000,
|
||||||
STR(Unknown13 ),// 0x80000000,
|
STR(Unknown13), // 0x80000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Flags, int N>
|
template<class Flags, int N>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue