OregonCore  revision fb2a440-git
Your Favourite TBC server
MoveSpline.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "MoveSpline.h"
19 #include <sstream>
20 #include "Log.h"
21 #include "Unit.h"
22 
23 namespace Movement
24 {
25  extern float computeFallTime(float path_length, bool isSafeFall);
26  extern float computeFallElevation(float time_passed, bool isSafeFall, float start_velocy);
27  extern float computeFallElevation(float time_passed);
28 
30  {
32 
33  float u = 1.f;
34  int32 seg_time = spline.length(point_Idx, point_Idx + 1);
35  if (seg_time > 0)
36  u = (time_passed - spline.length(point_Idx)) / (float)seg_time;
37  Location c;
39 
40  if (splineflags.falling)
42 
44  {
47  else if (splineflags.final_point)
48  c.orientation = atan2(facing.f.y - c.y, facing.f.x - c.x);
49  // nothing to do for MoveSplineFlag::Final_Target flag
50  }
51  else
52  {
53  Vector3 hermite;
55  c.orientation = atan2(hermite.y, hermite.x);
56  }
57  return c;
58  }
59 
60  void MoveSpline::computeFallElevation(float& el) const
61  {
62  float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed));
63  float final_z = FinalDestination().z;
64  if (z_now < final_z)
65  el = final_z;
66  else
67  el = z_now;
68  }
69 
70  inline uint32 computeDuration(float length, float velocity)
71  {
72  return SecToMS(length / velocity);
73  }
74 
76  {
77  FallInitializer(float _start_elevation) : start_elevation(_start_elevation) {}
80  {
81  return Movement::computeFallTime(start_elevation - s.getPoint(i + 1).z, false) * 1000.f;
82  }
83  };
84 
85  enum
86  {
88  };
89 
91  {
92  CommonInitializer(float _velocity) : velocityInv(1000.f / _velocity), time(minimal_duration) {}
93  float velocityInv;
96  {
97  time += (s.SegLength(i) * velocityInv);
98  return time;
99  }
100  };
101 
103  {
105  if (args.flags.cyclic)
106  {
107  uint32 cyclic_point = 0;
108  // MoveSplineFlag::Enter_Cycle support dropped
109  // if (splineflags & SPLINEFLAG_ENTER_CYCLE)
110  // cyclic_point = 1; // shouldn't be modified, came from client
111  spline.init_cyclic_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], cyclic_point);
112  }
113  else
114  {
115  spline.init_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()]);
116  }
117 
118  // init spline timestamps
119  if (splineflags.falling)
120  {
122  spline.initLengths(init);
123  }
124  else
125  {
126  CommonInitializer init(args.velocity);
127  spline.initLengths(init);
128  }
129 
130  // TODO: what to do in such cases? problem is in input data (all points are at same coords)
132  {
133  sLog.outError("MoveSpline::init_spline: zero length spline, wrong input data?");
134  spline.set_length(spline.last(), spline.isCyclic() ? 1000 : 1);
135  }
136  point_Idx = spline.first();
137  }
138 
140  {
141  splineflags = args.flags;
142  facing = args.facing;
143  m_Id = args.splineId;
145  time_passed = 0;
146 
147  // detect Stop command
148  if (splineflags.done)
149  {
150  spline.clear();
151  return;
152  }
153 
154  init_spline(args);
155  }
156 
157  MoveSpline::MoveSpline() : m_Id(0), time_passed(0), point_Idx(0), point_Idx_offset(0)
158  {
159  splineflags.done = true;
160  }
161 
163 
165  {
166 #define CHECK(exp) \
167  if (!(exp))\
168  {\
169  sLog.outError("MoveSplineInitArgs::Validate: expression '%s' failed for %s", #exp, unit->GetGuidStr().c_str());\
170  return false;\
171  }
172  CHECK(path.size() > 1);
173  CHECK(velocity > 0.f);
174  // CHECK(_checkPathBounds());
175  return true;
176 #undef CHECK
177  }
178 
179 // MONSTER_MOVE packet format limitation for not CatmullRom movement:
180 // each vertex offset packed into 11 bytes
182  {
183  if (!(flags & MoveSplineFlag::Mask_CatmullRom) && path.size() > 2)
184  {
185  enum
186  {
187  MAX_OFFSET = (1 << 11) / 2,
188  };
189  Vector3 middle = (path.front() + path.back()) / 2;
190  Vector3 offset;
191  for (uint32 i = 1; i < path.size() - 1; ++i)
192  {
193  offset = path[i] - middle;
194  if (fabs(offset.x) >= MAX_OFFSET || fabs(offset.y) >= MAX_OFFSET || fabs(offset.z) >= MAX_OFFSET)
195  {
196  sLog.outError("MoveSplineInitArgs::_checkPathBounds check failed");
197  return false;
198  }
199  }
200  }
201  return true;
202  }
203 
205 
207  {
208  if (Finalized())
209  {
210  ms_time_diff = 0;
211  return Result_Arrived;
212  }
213 
214  UpdateResult result = Result_None;
215 
216  int32 minimal_diff = std::min(ms_time_diff, segment_time_elapsed());
217  ASSERT(minimal_diff >= 0);
218  time_passed += minimal_diff;
219  ms_time_diff -= minimal_diff;
220 
221  if (time_passed >= next_timestamp())
222  {
223  ++point_Idx;
224  if (point_Idx < spline.last())
225  {
226  result = Result_NextSegment;
227  }
228  else
229  {
230  if (spline.isCyclic())
231  {
232  point_Idx = spline.first();
233  time_passed = time_passed % Duration();
234  result = Result_NextSegment;
235  }
236  else
237  {
238  _Finalize();
239  ms_time_diff = 0;
240  result = Result_Arrived;
241  }
242  }
243  }
244 
245  return result;
246  }
247 
248  std::string MoveSpline::ToString() const
249  {
250  std::stringstream str;
251  str << "MoveSpline" << std::endl;
252  str << "spline Id: " << GetId() << std::endl;
253  str << "flags: " << splineflags.ToString() << std::endl;
255  str << "facing angle: " << facing.angle;
256  else if (splineflags.final_target)
257  str << "facing target: " << facing.target;
258  else if (splineflags.final_point)
259  str << "facing point: " << facing.f.x << " " << facing.f.y << " " << facing.f.z;
260  str << std::endl;
261  str << "time passed: " << time_passed << std::endl;
262  str << "total time: " << Duration() << std::endl;
263  str << "spline point Id: " << point_Idx << std::endl;
264  str << "path point Id: " << currentPathIdx() << std::endl;
265  str << spline.ToString();
266  return str.str();
267  }
268 
270  {
271  splineflags.done = true;
272  point_Idx = spline.last() - 1;
273  time_passed = Duration();
274  }
275 
277  {
278  int32 point = point_Idx_offset + point_Idx - spline.first() + (int)Finalized();
279  if (isCyclic())
280  point = point % (spline.last() - spline.first());
281  return point;
282  }
283 }
#define CHECK(exp)
int32 currentPathIdx() const
Definition: MoveSpline.cpp:276
int32 operator()(Spline< int32 > &s, int32 i)
Definition: MoveSpline.cpp:79
int32 segment_time_elapsed() const
Definition: MoveSpline.h:81
const Vector3 FinalDestination() const
Definition: MoveSpline.h:120
void init_spline(const Vector3 *controls, index_type count, EvaluationMode m)
Definition: spline.h:171
void initLengths()
Definition: spline.impl.h:78
void evaluate_percent(float t, Vector3 &c) const
Definition: spline.impl.h:20
void init_spline(const MoveSplineInitArgs &args)
Definition: MoveSpline.cpp:102
MoveSplineFlag splineflags
Definition: MoveSpline.h:67
FallInitializer(float _start_elevation)
Definition: MoveSpline.cpp:77
#define sLog
Log class singleton.
Definition: Log.h:187
void Initialize(const MoveSplineInitArgs &)
Definition: MoveSpline.cpp:139
int32 operator()(Spline< int32 > &s, int32 i)
Definition: MoveSpline.cpp:95
ACE_INT32 int32
Definition: Define.h:67
uint32 computeDuration(float length, float velocity)
Definition: MoveSpline.cpp:70
float SegLength(index_type i) const
Definition: spline.h:128
std::string ToString() const
Definition: util.cpp:201
index_type first() const
Definition: spline.h:103
bool Initialized() const
Definition: MoveSpline.h:94
uint32 SecToMS(float sec)
Definition: typedefs.h:36
bool Validate(Unit *unit) const
============================================================================================ ...
Definition: MoveSpline.cpp:164
struct Movement::FacingInfo::@96 f
float computeFallTime(float path_length, bool isSafeFall)
Definition: util.cpp:34
float MSToSec(uint32 ms)
Definition: typedefs.h:41
CommonInitializer(float _velocity)
Definition: MoveSpline.cpp:92
length_type length() const
Definition: spline.h:199
void computeFallElevation(float &el) const
Definition: MoveSpline.cpp:60
const Vector3 & getPoint(index_type i) const
Definition: spline.h:112
bool Finalized() const
Definition: MoveSpline.h:117
void init_cyclic_spline(const Vector3 *controls, index_type count, EvaluationMode m, index_type cyclic_point)
Definition: spline.h:172
std::string ToString() const
Definition: MoveSpline.cpp:248
index_type last() const
Definition: spline.h:104
std::string ToString() const
Definition: spline.cpp:292
float computeFallElevation(float time_passed, bool isSafeFall, float start_velocy)
Definition: util.cpp:58
int32 Duration() const
Definition: MoveSpline.h:124
uint32 GetId() const
Definition: MoveSpline.h:116
void set_length(index_type i, length_type length)
Definition: spline.h:204
UpdateResult _updateState(int32 &ms_time_diff)
============================================================================================ ...
Definition: MoveSpline.cpp:206
Location ComputePosition() const
Definition: MoveSpline.cpp:29
#define ASSERT
Definition: Errors.h:29
FacingInfo facing
Definition: MoveSpline.h:63
int32 next_timestamp() const
Definition: MoveSpline.h:80
bool isCyclic() const
Definition: spline.h:108
ACE_UINT32 uint32
Definition: Define.h:71
bool isCyclic() const
Definition: MoveSpline.h:118
Definition: Unit.h:908
void evaluate_derivative(float t, Vector3 &hermite) const
Definition: spline.impl.h:28