pathManager.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "gfx/gfxDevice.h"
  23. #include "scene/pathManager.h"
  24. #include "sim/netConnection.h"
  25. #include "core/stream/bitStream.h"
  26. #include "scene/simPath.h"
  27. #include "math/mathIO.h"
  28. #include "scene/sceneRenderState.h"
  29. #include "scene/sceneManager.h"
  30. #include "platform/profiler.h"
  31. #include "core/module.h"
  32. #include "console/engineAPI.h"
  33. extern bool gEditingMission;
  34. namespace {
  35. U32 countNumBits(U32 n)
  36. {
  37. U32 count = 0;
  38. while (n != 0) {
  39. n >>= 1;
  40. count++;
  41. }
  42. return count ? count : 1;
  43. }
  44. } // namespace {}
  45. MODULE_BEGIN( PathManager )
  46. MODULE_INIT
  47. {
  48. AssertFatal(gClientPathManager == NULL && gServerPathManager == NULL, "Error, already initialized the path manager!");
  49. gClientPathManager = new PathManager(false);
  50. gServerPathManager = new PathManager(true);
  51. }
  52. MODULE_SHUTDOWN
  53. {
  54. AssertFatal(gClientPathManager != NULL && gServerPathManager != NULL, "Error, path manager not initialized!");
  55. delete gClientPathManager;
  56. gClientPathManager = NULL;
  57. delete gServerPathManager;
  58. gServerPathManager = NULL;
  59. }
  60. MODULE_END;
  61. //--------------------------------------------------------------------------
  62. //-------------------------------------- PathManagerEvent
  63. //
  64. class PathManagerEvent : public NetEvent
  65. {
  66. public:
  67. U32 modifiedPath;
  68. bool clearPaths;
  69. PathManager::PathEntry path;
  70. public:
  71. typedef NetEvent Parent;
  72. PathManagerEvent() : modifiedPath(0), clearPaths(false) { }
  73. void pack(NetConnection*, BitStream*);
  74. void write(NetConnection*, BitStream*);
  75. void unpack(NetConnection*, BitStream*);
  76. void process(NetConnection*);
  77. DECLARE_CONOBJECT(PathManagerEvent);
  78. };
  79. void PathManagerEvent::pack(NetConnection*, BitStream* stream)
  80. {
  81. // Write out the modified path...
  82. stream->write(modifiedPath);
  83. stream->writeFlag(clearPaths);
  84. stream->write(path.totalTime);
  85. stream->write(path.positions.size());
  86. // This is here for safety. You can remove it if you want to try your luck at bigger sizes. -- BJG
  87. AssertWarn(path.positions.size() < 1500/40, "Warning! Path size is pretty big - may cause packet overrun!");
  88. // Each one of these is about 8 floats and 2 ints
  89. // so we'll say it's about 40 bytes in size, which is where the 40 in the above calc comes from.
  90. for (U32 j = 0; j < path.positions.size(); j++)
  91. {
  92. mathWrite(*stream, path.positions[j]);
  93. mathWrite(*stream, path.rotations[j]);
  94. stream->write(path.msToNext[j]);
  95. stream->write(path.smoothingType[j]);
  96. }
  97. }
  98. void PathManagerEvent::write(NetConnection*nc, BitStream *stream)
  99. {
  100. pack(nc, stream);
  101. }
  102. void PathManagerEvent::unpack(NetConnection*, BitStream* stream)
  103. {
  104. // Read in the modified path...
  105. stream->read(&modifiedPath);
  106. clearPaths = stream->readFlag();
  107. stream->read(&path.totalTime);
  108. U32 numPoints;
  109. stream->read(&numPoints);
  110. path.positions.setSize(numPoints);
  111. path.rotations.setSize(numPoints);
  112. path.msToNext.setSize(numPoints);
  113. path.smoothingType.setSize(numPoints);
  114. for (U32 j = 0; j < path.positions.size(); j++)
  115. {
  116. mathRead(*stream, &path.positions[j]);
  117. mathRead(*stream, &path.rotations[j]);
  118. stream->read(&path.msToNext[j]);
  119. stream->read(&path.smoothingType[j]);
  120. }
  121. }
  122. void PathManagerEvent::process(NetConnection*)
  123. {
  124. if (clearPaths)
  125. {
  126. // Clear out all the client's paths...
  127. gClientPathManager->clearPaths();
  128. }
  129. AssertFatal(modifiedPath <= gClientPathManager->mPaths.size(), "Error out of bounds path!");
  130. if (modifiedPath == gClientPathManager->mPaths.size()) {
  131. PathManager::PathEntry *pe = new PathManager::PathEntry;
  132. *pe = path;
  133. gClientPathManager->mPaths.push_back(pe);
  134. }
  135. else
  136. *(gClientPathManager->mPaths[modifiedPath]) = path;
  137. }
  138. IMPLEMENT_CO_NETEVENT_V1(PathManagerEvent);
  139. // Will be internalized once the @internal tag is working
  140. ConsoleDocClass( PathManagerEvent,
  141. "@brief Class responsible for the registration, transmission, and management "
  142. "of paths on client and server.\n\n"
  143. "For internal use only, not intended for use in TorqueScript or game development\n\n"
  144. "@internal\n"
  145. );
  146. //--------------------------------------------------------------------------
  147. //-------------------------------------- PathManager Implementation
  148. //
  149. PathManager* gClientPathManager = NULL;
  150. PathManager* gServerPathManager = NULL;
  151. //--------------------------------------------------------------------------
  152. PathManager::PathManager(const bool isServer)
  153. {
  154. VECTOR_SET_ASSOCIATION(mPaths);
  155. mIsServer = isServer;
  156. }
  157. PathManager::~PathManager()
  158. {
  159. clearPaths();
  160. }
  161. void PathManager::clearPaths()
  162. {
  163. for (U32 i = 0; i < mPaths.size(); i++)
  164. delete mPaths[i];
  165. mPaths.setSize(0);
  166. #ifdef TORQUE_DEBUG
  167. // This gets rid of the memory used by the vector.
  168. // Prevents it from showing up in memory leak logs.
  169. mPaths.compact();
  170. #endif
  171. }
  172. DefineConsoleFunction( clearServerPaths, void, ( ), , "")
  173. {
  174. gServerPathManager->clearPaths();
  175. }
  176. DefineConsoleFunction( clearClientPaths, void, ( ), , "")
  177. {
  178. gClientPathManager->clearPaths();
  179. }
  180. //--------------------------------------------------------------------------
  181. U32 PathManager::allocatePathId()
  182. {
  183. mPaths.increment();
  184. mPaths.last() = new PathEntry;
  185. return (mPaths.size() - 1);
  186. }
  187. void PathManager::updatePath(const U32 id,
  188. const Vector<Point3F>& positions,
  189. const Vector<QuatF>& rotations,
  190. const Vector<U32>& times,
  191. const Vector<U32>& smoothingTypes)
  192. {
  193. AssertFatal(mIsServer == true, "PathManager::updatePath: Error, must be called on the server side");
  194. AssertFatal(id < mPaths.size(), "PathManager::updatePath: error, id out of range");
  195. AssertFatal(positions.size() == times.size() && positions.size() == smoothingTypes.size(), "Error, times and positions must match!");
  196. PathEntry& rEntry = *mPaths[id];
  197. rEntry.positions = positions;
  198. rEntry.rotations = rotations;
  199. rEntry.msToNext = times;
  200. rEntry.smoothingType = smoothingTypes;
  201. rEntry.totalTime = 0;
  202. for (S32 i = 0; i < S32(rEntry.msToNext.size()); i++)
  203. rEntry.totalTime += rEntry.msToNext[i];
  204. transmitPath(id);
  205. }
  206. //--------------------------------------------------------------------------
  207. void PathManager::transmitPaths(NetConnection* nc)
  208. {
  209. AssertFatal(mIsServer, "Error, cannot call transmitPaths on client path manager!");
  210. // Send over paths
  211. for(S32 i = 0; i < mPaths.size(); i++)
  212. {
  213. PathManagerEvent* event = new PathManagerEvent;
  214. event->clearPaths = (i == 0);
  215. event->modifiedPath = i;
  216. event->path = *(mPaths[i]);
  217. nc->postNetEvent(event);
  218. }
  219. }
  220. void PathManager::transmitPath(const U32 id)
  221. {
  222. AssertFatal(mIsServer, "Error, cannot call transmitNewPath on client path manager!");
  223. // Post to all active clients that have already received their paths...
  224. //
  225. SimGroup* pClientGroup = Sim::getClientGroup();
  226. for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++) {
  227. NetConnection* nc = dynamic_cast<NetConnection*>(*itr);
  228. if (nc && nc->missionPathsSent())
  229. {
  230. // Transmit the updated path...
  231. PathManagerEvent* event = new PathManagerEvent;
  232. event->modifiedPath = id;
  233. event->clearPaths = false;
  234. event->path = *(mPaths[id]);
  235. nc->postNetEvent(event);
  236. }
  237. }
  238. }
  239. void PathManager::getPathPosition(const U32 id,
  240. const F64 msPosition,
  241. Point3F& rPosition,
  242. QuatF &rotation)
  243. {
  244. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  245. PROFILE_START(PathManGetPos);
  246. // Ok, query holds our path information...
  247. F64 ms = msPosition;
  248. if (ms > mPaths[id]->totalTime)
  249. ms = mPaths[id]->totalTime;
  250. S32 startNode = 0;
  251. while (ms > mPaths[id]->msToNext[startNode]) {
  252. ms -= mPaths[id]->msToNext[startNode];
  253. startNode++;
  254. }
  255. S32 endNode = (startNode + 1) % mPaths[id]->positions.size();
  256. Point3F& rStart = mPaths[id]->positions[startNode];
  257. Point3F& rEnd = mPaths[id]->positions[endNode];
  258. F64 interp = ms / F32(mPaths[id]->msToNext[startNode]);
  259. if(mPaths[id]->smoothingType[startNode] == Marker::SmoothingTypeLinear)
  260. {
  261. rPosition = (rStart * (1.0 - interp)) + (rEnd * interp);
  262. }
  263. else if(mPaths[id]->smoothingType[startNode] == Marker::SmoothingTypeAccelerate)
  264. {
  265. interp = mSin(interp * M_PI - (M_PI / 2)) * 0.5 + 0.5;
  266. rPosition = (rStart * (1.0 - interp)) + (rEnd * interp);
  267. }
  268. else if(mPaths[id]->smoothingType[startNode] == Marker::SmoothingTypeSpline)
  269. {
  270. S32 preStart = startNode - 1;
  271. S32 postEnd = endNode + 1;
  272. if(postEnd >= mPaths[id]->positions.size())
  273. postEnd = 0;
  274. if(preStart < 0)
  275. preStart = mPaths[id]->positions.size() - 1;
  276. Point3F p0 = mPaths[id]->positions[preStart];
  277. Point3F p1 = rStart;
  278. Point3F p2 = rEnd;
  279. Point3F p3 = mPaths[id]->positions[postEnd];
  280. rPosition.x = mCatmullrom(interp, p0.x, p1.x, p2.x, p3.x);
  281. rPosition.y = mCatmullrom(interp, p0.y, p1.y, p2.y, p3.y);
  282. rPosition.z = mCatmullrom(interp, p0.z, p1.z, p2.z, p3.z);
  283. }
  284. rotation.interpolate( mPaths[id]->rotations[startNode], mPaths[id]->rotations[endNode], interp );
  285. PROFILE_END();
  286. }
  287. U32 PathManager::getPathTotalTime(const U32 id) const
  288. {
  289. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  290. return mPaths[id]->totalTime;
  291. }
  292. U32 PathManager::getPathNumWaypoints(const U32 id) const
  293. {
  294. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  295. return mPaths[id]->positions.size();
  296. }
  297. U32 PathManager::getWaypointTime(const U32 id, const U32 wayPoint) const
  298. {
  299. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  300. AssertFatal(wayPoint < getPathNumWaypoints(id), "Invalid waypoint!");
  301. U32 time = 0;
  302. for (U32 i = 0; i < wayPoint; i++)
  303. time += mPaths[id]->msToNext[i];
  304. return time;
  305. }
  306. U32 PathManager::getPathTimeBits(const U32 id)
  307. {
  308. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  309. return countNumBits(mPaths[id]->totalTime);
  310. }
  311. U32 PathManager::getPathWaypointBits(const U32 id)
  312. {
  313. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  314. return countNumBits(mPaths[id]->positions.size());
  315. }
  316. bool PathManager::dumpState(BitStream* stream) const
  317. {
  318. stream->write(mPaths.size());
  319. for (U32 i = 0; i < mPaths.size(); i++) {
  320. const PathEntry& rEntry = *mPaths[i];
  321. stream->write(rEntry.totalTime);
  322. stream->write(rEntry.positions.size());
  323. for (U32 j = 0; j < rEntry.positions.size(); j++) {
  324. mathWrite(*stream, rEntry.positions[j]);
  325. stream->write(rEntry.msToNext[j]);
  326. }
  327. }
  328. return stream->getStatus() == Stream::Ok;
  329. }
  330. bool PathManager::readState(BitStream* stream)
  331. {
  332. U32 i;
  333. for (i = 0; i < mPaths.size(); i++)
  334. delete mPaths[i];
  335. U32 numPaths;
  336. stream->read(&numPaths);
  337. mPaths.setSize(numPaths);
  338. for (i = 0; i < mPaths.size(); i++) {
  339. mPaths[i] = new PathEntry;
  340. PathEntry& rEntry = *mPaths[i];
  341. stream->read(&rEntry.totalTime);
  342. U32 numPositions;
  343. stream->read(&numPositions);
  344. rEntry.positions.setSize(numPositions);
  345. rEntry.msToNext.setSize(numPositions);
  346. for (U32 j = 0; j < rEntry.positions.size(); j++) {
  347. mathRead(*stream, &rEntry.positions[j]);
  348. stream->read(&rEntry.msToNext[j]);
  349. }
  350. }
  351. return stream->getStatus() == Stream::Ok;
  352. }