pathManager.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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. extern bool gEditingMission;
  33. namespace {
  34. U32 countNumBits(U32 n)
  35. {
  36. U32 count = 0;
  37. while (n != 0) {
  38. n >>= 1;
  39. count++;
  40. }
  41. return count ? count : 1;
  42. }
  43. } // namespace {}
  44. MODULE_BEGIN( PathManager )
  45. MODULE_INIT
  46. {
  47. AssertFatal(gClientPathManager == NULL && gServerPathManager == NULL, "Error, already initialized the path manager!");
  48. gClientPathManager = new PathManager(false);
  49. gServerPathManager = new PathManager(true);
  50. }
  51. MODULE_SHUTDOWN
  52. {
  53. AssertFatal(gClientPathManager != NULL && gServerPathManager != NULL, "Error, path manager not initialized!");
  54. delete gClientPathManager;
  55. gClientPathManager = NULL;
  56. delete gServerPathManager;
  57. gServerPathManager = NULL;
  58. }
  59. MODULE_END;
  60. //--------------------------------------------------------------------------
  61. //-------------------------------------- PathManagerEvent
  62. //
  63. class PathManagerEvent : public NetEvent
  64. {
  65. public:
  66. U32 modifiedPath;
  67. bool clearPaths;
  68. PathManager::PathEntry path;
  69. public:
  70. typedef NetEvent Parent;
  71. PathManagerEvent() { }
  72. void pack(NetConnection*, BitStream*);
  73. void write(NetConnection*, BitStream*);
  74. void unpack(NetConnection*, BitStream*);
  75. void process(NetConnection*);
  76. DECLARE_CONOBJECT(PathManagerEvent);
  77. };
  78. void PathManagerEvent::pack(NetConnection*, BitStream* stream)
  79. {
  80. // Write out the modified path...
  81. stream->write(modifiedPath);
  82. stream->writeFlag(clearPaths);
  83. stream->write(path.totalTime);
  84. stream->write(path.positions.size());
  85. // This is here for safety. You can remove it if you want to try your luck at bigger sizes. -- BJG
  86. AssertWarn(path.positions.size() < 1500/40, "Warning! Path size is pretty big - may cause packet overrun!");
  87. // Each one of these is about 8 floats and 2 ints
  88. // so we'll say it's about 40 bytes in size, which is where the 40 in the above calc comes from.
  89. for (U32 j = 0; j < path.positions.size(); j++)
  90. {
  91. mathWrite(*stream, path.positions[j]);
  92. mathWrite(*stream, path.rotations[j]);
  93. stream->write(path.msToNext[j]);
  94. stream->write(path.smoothingType[j]);
  95. }
  96. }
  97. void PathManagerEvent::write(NetConnection*nc, BitStream *stream)
  98. {
  99. pack(nc, stream);
  100. }
  101. void PathManagerEvent::unpack(NetConnection*, BitStream* stream)
  102. {
  103. // Read in the modified path...
  104. stream->read(&modifiedPath);
  105. clearPaths = stream->readFlag();
  106. stream->read(&path.totalTime);
  107. U32 numPoints;
  108. stream->read(&numPoints);
  109. path.positions.setSize(numPoints);
  110. path.rotations.setSize(numPoints);
  111. path.msToNext.setSize(numPoints);
  112. path.smoothingType.setSize(numPoints);
  113. for (U32 j = 0; j < path.positions.size(); j++)
  114. {
  115. mathRead(*stream, &path.positions[j]);
  116. mathRead(*stream, &path.rotations[j]);
  117. stream->read(&path.msToNext[j]);
  118. stream->read(&path.smoothingType[j]);
  119. }
  120. }
  121. void PathManagerEvent::process(NetConnection*)
  122. {
  123. if (clearPaths)
  124. {
  125. // Clear out all the client's paths...
  126. gClientPathManager->clearPaths();
  127. }
  128. AssertFatal(modifiedPath <= gClientPathManager->mPaths.size(), "Error out of bounds path!");
  129. if (modifiedPath == gClientPathManager->mPaths.size()) {
  130. PathManager::PathEntry *pe = new PathManager::PathEntry;
  131. *pe = path;
  132. gClientPathManager->mPaths.push_back(pe);
  133. }
  134. else
  135. *(gClientPathManager->mPaths[modifiedPath]) = path;
  136. }
  137. IMPLEMENT_CO_NETEVENT_V1(PathManagerEvent);
  138. // Will be internalized once the @internal tag is working
  139. ConsoleDocClass( PathManagerEvent,
  140. "@brief Class responsible for the registration, transmission, and management "
  141. "of paths on client and server.\n\n"
  142. "For internal use only, not intended for use in TorqueScript or game development\n\n"
  143. "@internal\n"
  144. );
  145. //--------------------------------------------------------------------------
  146. //-------------------------------------- PathManager Implementation
  147. //
  148. PathManager* gClientPathManager = NULL;
  149. PathManager* gServerPathManager = NULL;
  150. //--------------------------------------------------------------------------
  151. PathManager::PathManager(const bool isServer)
  152. {
  153. VECTOR_SET_ASSOCIATION(mPaths);
  154. mIsServer = isServer;
  155. }
  156. PathManager::~PathManager()
  157. {
  158. clearPaths();
  159. }
  160. void PathManager::clearPaths()
  161. {
  162. for (U32 i = 0; i < mPaths.size(); i++)
  163. delete mPaths[i];
  164. mPaths.setSize(0);
  165. #ifdef TORQUE_DEBUG
  166. // This gets rid of the memory used by the vector.
  167. // Prevents it from showing up in memory leak logs.
  168. mPaths.compact();
  169. #endif
  170. }
  171. ConsoleFunction(clearServerPaths, void, 1, 1, "")
  172. {
  173. gServerPathManager->clearPaths();
  174. }
  175. ConsoleFunction(clearClientPaths, void, 1, 1, "")
  176. {
  177. gClientPathManager->clearPaths();
  178. }
  179. //--------------------------------------------------------------------------
  180. U32 PathManager::allocatePathId()
  181. {
  182. mPaths.increment();
  183. mPaths.last() = new PathEntry;
  184. return (mPaths.size() - 1);
  185. }
  186. void PathManager::updatePath(const U32 id,
  187. const Vector<Point3F>& positions,
  188. const Vector<QuatF>& rotations,
  189. const Vector<U32>& times,
  190. const Vector<U32>& smoothingTypes)
  191. {
  192. AssertFatal(mIsServer == true, "PathManager::updatePath: Error, must be called on the server side");
  193. AssertFatal(id < mPaths.size(), "PathManager::updatePath: error, id out of range");
  194. AssertFatal(positions.size() == times.size() && positions.size() == smoothingTypes.size(), "Error, times and positions must match!");
  195. PathEntry& rEntry = *mPaths[id];
  196. rEntry.positions = positions;
  197. rEntry.rotations = rotations;
  198. rEntry.msToNext = times;
  199. rEntry.smoothingType = smoothingTypes;
  200. rEntry.totalTime = 0;
  201. for (S32 i = 0; i < S32(rEntry.msToNext.size()); i++)
  202. rEntry.totalTime += rEntry.msToNext[i];
  203. transmitPath(id);
  204. }
  205. //--------------------------------------------------------------------------
  206. void PathManager::transmitPaths(NetConnection* nc)
  207. {
  208. AssertFatal(mIsServer, "Error, cannot call transmitPaths on client path manager!");
  209. // Send over paths
  210. for(S32 i = 0; i < mPaths.size(); i++)
  211. {
  212. PathManagerEvent* event = new PathManagerEvent;
  213. event->clearPaths = (i == 0);
  214. event->modifiedPath = i;
  215. event->path = *(mPaths[i]);
  216. nc->postNetEvent(event);
  217. }
  218. }
  219. void PathManager::transmitPath(const U32 id)
  220. {
  221. AssertFatal(mIsServer, "Error, cannot call transmitNewPath on client path manager!");
  222. // Post to all active clients that have already received their paths...
  223. //
  224. SimGroup* pClientGroup = Sim::getClientGroup();
  225. for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++) {
  226. NetConnection* nc = dynamic_cast<NetConnection*>(*itr);
  227. if (nc && nc->missionPathsSent())
  228. {
  229. // Transmit the updated path...
  230. PathManagerEvent* event = new PathManagerEvent;
  231. event->modifiedPath = id;
  232. event->clearPaths = false;
  233. event->path = *(mPaths[id]);
  234. nc->postNetEvent(event);
  235. }
  236. }
  237. }
  238. void PathManager::getPathPosition(const U32 id,
  239. const F64 msPosition,
  240. Point3F& rPosition,
  241. QuatF &rotation)
  242. {
  243. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  244. PROFILE_START(PathManGetPos);
  245. // Ok, query holds our path information...
  246. F64 ms = msPosition;
  247. if (ms > mPaths[id]->totalTime)
  248. ms = mPaths[id]->totalTime;
  249. S32 startNode = 0;
  250. while (ms > mPaths[id]->msToNext[startNode]) {
  251. ms -= mPaths[id]->msToNext[startNode];
  252. startNode++;
  253. }
  254. S32 endNode = (startNode + 1) % mPaths[id]->positions.size();
  255. Point3F& rStart = mPaths[id]->positions[startNode];
  256. Point3F& rEnd = mPaths[id]->positions[endNode];
  257. F64 interp = ms / F32(mPaths[id]->msToNext[startNode]);
  258. if(mPaths[id]->smoothingType[startNode] == Marker::SmoothingTypeLinear)
  259. {
  260. rPosition = (rStart * (1.0 - interp)) + (rEnd * interp);
  261. }
  262. else if(mPaths[id]->smoothingType[startNode] == Marker::SmoothingTypeAccelerate)
  263. {
  264. interp = mSin(interp * M_PI - (M_PI / 2)) * 0.5 + 0.5;
  265. rPosition = (rStart * (1.0 - interp)) + (rEnd * interp);
  266. }
  267. else if(mPaths[id]->smoothingType[startNode] == Marker::SmoothingTypeSpline)
  268. {
  269. S32 preStart = startNode - 1;
  270. S32 postEnd = endNode + 1;
  271. if(postEnd >= mPaths[id]->positions.size())
  272. postEnd = 0;
  273. if(preStart < 0)
  274. preStart = mPaths[id]->positions.size() - 1;
  275. Point3F p0 = mPaths[id]->positions[preStart];
  276. Point3F p1 = rStart;
  277. Point3F p2 = rEnd;
  278. Point3F p3 = mPaths[id]->positions[postEnd];
  279. rPosition.x = mCatmullrom(interp, p0.x, p1.x, p2.x, p3.x);
  280. rPosition.y = mCatmullrom(interp, p0.y, p1.y, p2.y, p3.y);
  281. rPosition.z = mCatmullrom(interp, p0.z, p1.z, p2.z, p3.z);
  282. }
  283. rotation.interpolate( mPaths[id]->rotations[startNode], mPaths[id]->rotations[endNode], interp );
  284. PROFILE_END();
  285. }
  286. U32 PathManager::getPathTotalTime(const U32 id) const
  287. {
  288. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  289. return mPaths[id]->totalTime;
  290. }
  291. U32 PathManager::getPathNumWaypoints(const U32 id) const
  292. {
  293. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  294. return mPaths[id]->positions.size();
  295. }
  296. U32 PathManager::getWaypointTime(const U32 id, const U32 wayPoint) const
  297. {
  298. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  299. AssertFatal(wayPoint < getPathNumWaypoints(id), "Invalid waypoint!");
  300. U32 time = 0;
  301. for (U32 i = 0; i < wayPoint; i++)
  302. time += mPaths[id]->msToNext[i];
  303. return time;
  304. }
  305. U32 PathManager::getPathTimeBits(const U32 id)
  306. {
  307. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  308. return countNumBits(mPaths[id]->totalTime);
  309. }
  310. U32 PathManager::getPathWaypointBits(const U32 id)
  311. {
  312. AssertFatal(isValidPath(id), "Error, this is not a valid path!");
  313. return countNumBits(mPaths[id]->positions.size());
  314. }
  315. bool PathManager::dumpState(BitStream* stream) const
  316. {
  317. stream->write(mPaths.size());
  318. for (U32 i = 0; i < mPaths.size(); i++) {
  319. const PathEntry& rEntry = *mPaths[i];
  320. stream->write(rEntry.totalTime);
  321. stream->write(rEntry.positions.size());
  322. for (U32 j = 0; j < rEntry.positions.size(); j++) {
  323. mathWrite(*stream, rEntry.positions[j]);
  324. stream->write(rEntry.msToNext[j]);
  325. }
  326. }
  327. return stream->getStatus() == Stream::Ok;
  328. }
  329. bool PathManager::readState(BitStream* stream)
  330. {
  331. U32 i;
  332. for (i = 0; i < mPaths.size(); i++)
  333. delete mPaths[i];
  334. U32 numPaths;
  335. stream->read(&numPaths);
  336. mPaths.setSize(numPaths);
  337. for (i = 0; i < mPaths.size(); i++) {
  338. mPaths[i] = new PathEntry;
  339. PathEntry& rEntry = *mPaths[i];
  340. stream->read(&rEntry.totalTime);
  341. U32 numPositions;
  342. stream->read(&numPositions);
  343. rEntry.positions.setSize(numPositions);
  344. rEntry.msToNext.setSize(numPositions);
  345. for (U32 j = 0; j < rEntry.positions.size(); j++) {
  346. mathRead(*stream, &rEntry.positions[j]);
  347. stream->read(&rEntry.msToNext[j]);
  348. }
  349. }
  350. return stream->getStatus() == Stream::Ok;
  351. }