extendedMove.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include "T3D/gameBase/extended/extendedMove.h"
  2. #include "core/stream/bitStream.h"
  3. #include "math/mathIO.h"
  4. #include "math/mAngAxis.h"
  5. #include "core/module.h"
  6. #include "console/consoleTypes.h"
  7. #include "core/strings/stringFunctions.h"
  8. MODULE_BEGIN( ExtendedMoveManager )
  9. MODULE_INIT_AFTER( MoveManager )
  10. MODULE_INIT
  11. {
  12. ExtendedMoveManager::init();
  13. }
  14. MODULE_END;
  15. S32 ExtendedMoveManager::mPosX[ExtendedMove::MaxPositionsRotations] = { 0, };
  16. S32 ExtendedMoveManager::mPosY[ExtendedMove::MaxPositionsRotations] = { 0, };
  17. S32 ExtendedMoveManager::mPosZ[ExtendedMove::MaxPositionsRotations] = { 0, };
  18. bool ExtendedMoveManager::mRotIsEuler[ExtendedMove::MaxPositionsRotations] = { 0, };
  19. F32 ExtendedMoveManager::mRotAX[ExtendedMove::MaxPositionsRotations] = { 0, };
  20. F32 ExtendedMoveManager::mRotAY[ExtendedMove::MaxPositionsRotations] = { 0, };
  21. F32 ExtendedMoveManager::mRotAZ[ExtendedMove::MaxPositionsRotations] = { 0, };
  22. F32 ExtendedMoveManager::mRotAA[ExtendedMove::MaxPositionsRotations] = { 1, };
  23. void ExtendedMoveManager::init()
  24. {
  25. for(U32 i = 0; i < ExtendedMove::MaxPositionsRotations; ++i)
  26. {
  27. char varName[256];
  28. dSprintf(varName, sizeof(varName), "mvPosX%d", i);
  29. Con::addVariable(varName, TypeS32, &mPosX[i],
  30. "X position of controller in millimeters. Only 13 bits are networked.\n"
  31. "@ingroup Game");
  32. dSprintf(varName, sizeof(varName), "mvPosY%d", i);
  33. Con::addVariable(varName, TypeS32, &mPosY[i],
  34. "Y position of controller in millimeters. Only 13 bits are networked.\n"
  35. "@ingroup Game");
  36. dSprintf(varName, sizeof(varName), "mvPosZ%d", i);
  37. Con::addVariable(varName, TypeS32, &mPosZ[i],
  38. "Z position of controller in millimeters. Only 13 bits are networked.\n"
  39. "@ingroup Game");
  40. dSprintf(varName, sizeof(varName), "mvRotIsEuler%d", i);
  41. Con::addVariable(varName, TypeBool, &mRotIsEuler[i],
  42. "@brief Indicates that the given rotation is Euler angles.\n\n"
  43. "When false (the default) the given rotation is a four component angled axis "
  44. "(a vector and angle). When true, the given rotation is a three component "
  45. "Euler angle. When using Euler angles, the $mvRotA component of the ExtendedMove "
  46. "is ignored for this set of rotations.\n"
  47. "@ingroup Game");
  48. dSprintf(varName, sizeof(varName), "mvRotX%d", i);
  49. Con::addVariable(varName, TypeF32, &mRotAX[i],
  50. "X rotation vector component of controller.\n"
  51. "@ingroup Game");
  52. dSprintf(varName, sizeof(varName), "mvRotY%d", i);
  53. Con::addVariable(varName, TypeF32, &mRotAY[i],
  54. "Y rotation vector component of controller.\n"
  55. "@ingroup Game");
  56. dSprintf(varName, sizeof(varName), "mvRotZ%d", i);
  57. Con::addVariable(varName, TypeF32, &mRotAZ[i],
  58. "Z rotation vector component of controller.\n"
  59. "@ingroup Game");
  60. dSprintf(varName, sizeof(varName), "mvRotA%d", i);
  61. Con::addVariable(varName, TypeF32, &mRotAA[i],
  62. "Angle rotation (in degrees) component of controller.\n"
  63. "@ingroup Game");
  64. }
  65. }
  66. const ExtendedMove NullExtendedMove;
  67. #define CLAMPPOS(x) ((S32)(((x + 1) * .5) * ((1 << MaxPositionBits) - 1)) & ((1<<MaxPositionBits)-1))
  68. #define UNCLAMPPOS(x) ((F32)(x * 2 / F32((1 << MaxPositionBits) - 1) - 1.0f))
  69. #define CLAMPROT(f) ((S32)(((f + 1) * .5) * ((1 << MaxRotationBits) - 1)) & ((1<<MaxRotationBits)-1))
  70. #define UNCLAMPROT(x) ((F32)(x * 2 / F32((1 << MaxRotationBits) - 1) - 1.0f))
  71. ExtendedMove::ExtendedMove() : Move()
  72. {
  73. for(U32 i=0; i<MaxPositionsRotations; ++i)
  74. {
  75. posX[i] = 0;
  76. posY[i] = 0;
  77. posZ[i] = 0;
  78. rotX[i] = 0;
  79. rotY[i] = 0;
  80. rotZ[i] = 0;
  81. rotW[i] = 1;
  82. cposX[i] = 0;
  83. cposY[i] = 0;
  84. cposZ[i] = 0;
  85. EulerBasedRotation[i] = false;
  86. }
  87. }
  88. void ExtendedMove::pack(BitStream *stream, const Move * basemove)
  89. {
  90. bool alwaysWriteAll = basemove!=NULL;
  91. if (!basemove)
  92. basemove = &NullExtendedMove;
  93. // Write the standard Move stuff
  94. packMove(stream, basemove, alwaysWriteAll);
  95. // Extended Move
  96. const ExtendedMove* extBaseMove = static_cast<const ExtendedMove*>(basemove);
  97. bool extendedDifferent = false;
  98. for(U32 i=0; i<MaxPositionsRotations; ++i)
  99. {
  100. bool check = (posX[i] != extBaseMove->posX[i]) ||
  101. (posY[i] != extBaseMove->posY[i]) ||
  102. (posZ[i] != extBaseMove->posZ[i]) ||
  103. (rotX[i] != extBaseMove->rotX[i]) ||
  104. (rotY[i] != extBaseMove->rotY[i]) ||
  105. (rotZ[i] != extBaseMove->rotZ[i]);
  106. if(!EulerBasedRotation[i])
  107. {
  108. check = check || (rotW[i] != extBaseMove->rotW[i]);
  109. }
  110. extendedDifferent = extendedDifferent || check;
  111. }
  112. if (alwaysWriteAll || stream->writeFlag(extendedDifferent))
  113. {
  114. for(U32 i=0; i<MaxPositionsRotations; ++i)
  115. {
  116. // Position
  117. if(stream->writeFlag(posX[i] != extBaseMove->posX[i]))
  118. stream->writeInt(cposX[i], MaxPositionBits);
  119. if(stream->writeFlag(posY[i] != extBaseMove->posY[i]))
  120. stream->writeInt(cposY[i], MaxPositionBits);
  121. if(stream->writeFlag(posZ[i] != extBaseMove->posZ[i]))
  122. stream->writeInt(cposZ[i], MaxPositionBits);
  123. // Rotation
  124. stream->writeFlag(EulerBasedRotation[i]);
  125. if(stream->writeFlag(rotX[i] != extBaseMove->rotX[i]))
  126. stream->writeInt(crotX[i], EulerBasedRotation[i] ? MaxRotationBits : MaxPositionBits);
  127. if(stream->writeFlag(rotY[i] != extBaseMove->rotY[i]))
  128. stream->writeInt(crotY[i], EulerBasedRotation[i] ? MaxRotationBits : MaxPositionBits);
  129. if(stream->writeFlag(rotZ[i] != extBaseMove->rotZ[i]))
  130. stream->writeInt(crotZ[i], EulerBasedRotation[i] ? MaxRotationBits : MaxPositionBits);
  131. if(!EulerBasedRotation[i])
  132. {
  133. if(stream->writeFlag(rotW[i] != extBaseMove->rotW[i]))
  134. stream->writeInt(crotW[i], MaxRotationBits);
  135. }
  136. }
  137. }
  138. }
  139. void ExtendedMove::unpack(BitStream *stream, const Move * basemove)
  140. {
  141. bool alwaysReadAll = basemove!=NULL;
  142. if (!basemove)
  143. basemove=&NullExtendedMove;
  144. // Standard Move stuff
  145. bool isBaseMove = !unpackMove(stream, basemove, alwaysReadAll);
  146. // ExtendedMove
  147. const ExtendedMove* extBaseMove = static_cast<const ExtendedMove*>(basemove);
  148. if (alwaysReadAll || stream->readFlag())
  149. {
  150. isBaseMove = false;
  151. for(U32 i=0; i<MaxPositionsRotations; ++i)
  152. {
  153. // Position
  154. if (stream->readFlag())
  155. {
  156. posX[i] = stream->readInt(MaxPositionBits);
  157. cposX[i] = UNCLAMPPOS(posX[i]);
  158. }
  159. else
  160. posX[i] = extBaseMove->posX[i];
  161. if (stream->readFlag())
  162. {
  163. cposY[i] = stream->readInt(MaxPositionBits);
  164. posY[i] = UNCLAMPPOS(cposY[i]);
  165. }
  166. else
  167. posY[i] = extBaseMove->posY[i];
  168. if (stream->readFlag())
  169. {
  170. cposZ[i] = stream->readInt(MaxPositionBits);
  171. posZ[i] = UNCLAMPPOS(cposZ[i]);
  172. }
  173. else
  174. posZ[i] = extBaseMove->posZ[i];
  175. // Rotation
  176. EulerBasedRotation[i] = stream->readFlag();
  177. F32 scale = 1.0f;
  178. if(EulerBasedRotation[i])
  179. scale = M_2PI_F;
  180. if(stream->readFlag())
  181. {
  182. crotX[i] = stream->readInt(EulerBasedRotation[i] ? MaxRotationBits : MaxPositionBits);
  183. rotX[i] = EulerBasedRotation[i] ? (UNCLAMPROT(crotX[i]) * scale) : UNCLAMPPOS(crotX[i]);
  184. }
  185. else
  186. {
  187. rotX[i] = extBaseMove->rotX[i];
  188. }
  189. if(stream->readFlag())
  190. {
  191. crotY[i] = stream->readInt(EulerBasedRotation[i] ? MaxRotationBits : MaxPositionBits);
  192. rotY[i] = EulerBasedRotation[i] ? (UNCLAMPROT(crotY[i]) * scale) : UNCLAMPPOS(crotY[i]);
  193. }
  194. else
  195. {
  196. rotY[i] = extBaseMove->rotY[i];
  197. }
  198. if(stream->readFlag())
  199. {
  200. crotZ[i] = stream->readInt(EulerBasedRotation[i] ? MaxRotationBits : MaxPositionBits);
  201. rotZ[i] = EulerBasedRotation[i] ? (UNCLAMPROT(crotZ[i]) * scale) : UNCLAMPPOS(crotZ[i]);
  202. }
  203. else
  204. {
  205. rotZ[i] = extBaseMove->rotZ[i];
  206. }
  207. if(!EulerBasedRotation[i])
  208. {
  209. if(stream->readFlag())
  210. {
  211. crotW[i] = stream->readInt(MaxRotationBits);
  212. rotW[i] = UNCLAMPROT(crotW[i]) * M_2PI_F;
  213. }
  214. else
  215. {
  216. rotW[i] = extBaseMove->rotW[i];
  217. }
  218. }
  219. }
  220. }
  221. if(isBaseMove)
  222. {
  223. *this = *extBaseMove;
  224. }
  225. }
  226. void ExtendedMove::clamp()
  227. {
  228. // Clamp the values the same as for net traffic so the client matches the server
  229. for(U32 i=0; i<MaxPositionsRotations; ++i)
  230. {
  231. // Positions
  232. cposX[i] = CLAMPPOS(posX[i]);
  233. cposY[i] = CLAMPPOS(posY[i]);
  234. cposZ[i] = CLAMPPOS(posZ[i]);
  235. // Rotations
  236. if(EulerBasedRotation[i])
  237. {
  238. crotX[i] = CLAMPROT(rotX[i] / M_2PI_F);
  239. crotY[i] = CLAMPROT(rotY[i] / M_2PI_F);
  240. crotZ[i] = CLAMPROT(rotZ[i] / M_2PI_F);
  241. }
  242. else
  243. {
  244. crotX[i] = CLAMPPOS(rotX[i]);
  245. crotY[i] = CLAMPPOS(rotY[i]);
  246. crotZ[i] = CLAMPPOS(rotZ[i]);
  247. crotW[i] = CLAMPROT(rotW[i] / M_2PI_F);
  248. }
  249. /*if (i == 0)
  250. {
  251. F32 x, y, z, a;
  252. x = UNCLAMPPOS(crotX[i]);
  253. y = UNCLAMPPOS(crotY[i]);
  254. z = UNCLAMPPOS(crotZ[i]);
  255. a = UNCLAMPROT(crotW[i]) * M_2PI_F;
  256. //Con::printf("rot %f,%f,%f,%f clamped to %f,%f,%f,%f", rotX[i], rotY[i], rotZ[i], rotW[i], x,y,z,a);
  257. }*/
  258. }
  259. // Perform the standard Move clamp
  260. Parent::clamp();
  261. }
  262. void ExtendedMove::unclamp()
  263. {
  264. // Unclamp the values the same as for net traffic so the client matches the server
  265. for(U32 i=0; i<MaxPositionsRotations; ++i)
  266. {
  267. posX[i] = UNCLAMPPOS(cposX[i]);
  268. posY[i] = UNCLAMPPOS(cposY[i]);
  269. posZ[i] = UNCLAMPPOS(cposZ[i]);
  270. // Rotations
  271. if(EulerBasedRotation[i])
  272. {
  273. rotX[i] = UNCLAMPROT(crotX[i]) * M_2PI_F;
  274. rotY[i] = UNCLAMPROT(crotY[i]) * M_2PI_F;
  275. rotZ[i] = UNCLAMPROT(crotZ[i]) * M_2PI_F;
  276. }
  277. else
  278. {
  279. rotX[i] = UNCLAMPPOS(crotX[i]);
  280. rotY[i] = UNCLAMPPOS(crotY[i]);
  281. rotZ[i] = UNCLAMPPOS(crotZ[i]);
  282. rotW[i] = UNCLAMPROT(crotW[i]) * M_2PI_F;
  283. }
  284. }
  285. // Perform the standard Move unclamp
  286. Parent::unclamp();
  287. }