VPathNode.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. //-----------------------------------------------------------------------------
  2. // Verve
  3. // Copyright (C) 2014 - Violent Tulip
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //-----------------------------------------------------------------------------
  23. #include "VPathNode.h"
  24. #include "VPath.h"
  25. #include "core/stream/bitStream.h"
  26. #include "core/strings/stringUnit.h"
  27. #include "sim/netConnection.h"
  28. //-----------------------------------------------------------------------------
  29. static U32 gOrientationTypeBits = getBinLog2( getNextPow2( VPathNode::k_OrientationTypeSize ) );
  30. //-----------------------------------------------------------------------------
  31. VPathNode::VPathNode( void ) :
  32. mPath( NULL ),
  33. mLocalPosition( Point3F( 0.f, 0.f, 0.f ) ),
  34. mLocalRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ),
  35. mWorldPosition( Point3F( 0.f, 0.f, 0.f ) ),
  36. mWorldRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ),
  37. mWeight( 10.f ),
  38. mLength( 0.f )
  39. {
  40. // Init.
  41. mOrientationMode.Type = k_OrientationFree;
  42. mOrientationMode.Point = Point3F::Zero;
  43. // Set the initial mask.
  44. mNetState.setMaskBits( k_StateInit );
  45. VECTOR_SET_ASSOCIATION( mNetState );
  46. }
  47. VPathNode::~VPathNode( void )
  48. {
  49. mNetState.clear();
  50. }
  51. //-----------------------------------------------------------------------------
  52. //
  53. // Network Methods.
  54. //
  55. //-----------------------------------------------------------------------------
  56. U32 VPathNode::packNode( NetConnection *pConnection, BitStream *pStream )
  57. {
  58. // Init Return Mask.
  59. U32 retMask = 0;
  60. // Fetch State.
  61. VNetStateInfo *state = getState( pConnection );
  62. // Note: This is out of sync with VPathNode::unpackUpdate().
  63. // If you're ever going to use these methods outside of VPath, you
  64. // will need to read a flag *before* calling unpack!
  65. // Was the Node Created?
  66. if ( pStream->writeFlag( state->Mask & k_StateCreate ) )
  67. {
  68. // Clear Update.
  69. state->Mask &= ~k_StateCreate;
  70. }
  71. // Send mLocalPosition?
  72. if ( pStream->writeFlag( state->Mask & k_StateUpdatePosition ) )
  73. {
  74. // Write mLocalPosition.
  75. pStream->write( mLocalPosition.x );
  76. pStream->write( mLocalPosition.y );
  77. pStream->write( mLocalPosition.z );
  78. // Clear Update.
  79. state->Mask &= ~k_StateUpdatePosition;
  80. }
  81. // Send mLocalRotation?
  82. if ( pStream->writeFlag( state->Mask & k_StateUpdateRotation ) )
  83. {
  84. // Write mLocalRotation.
  85. pStream->write( mLocalRotation.x );
  86. pStream->write( mLocalRotation.y );
  87. pStream->write( mLocalRotation.z );
  88. pStream->write( mLocalRotation.w );
  89. // Clear Update.
  90. state->Mask &= ~k_StateUpdateRotation;
  91. }
  92. // Send mWeight?
  93. if ( pStream->writeFlag( state->Mask & k_StateUpdateWeight ) )
  94. {
  95. // Write mWeight.
  96. pStream->write( mWeight );
  97. // Clear Update.
  98. state->Mask &= ~k_StateUpdateWeight;
  99. }
  100. // Send Orientation Update?
  101. if ( pStream->writeFlag( state->Mask & k_StateUpdateOrientation ) )
  102. {
  103. // Clear Update?
  104. bool clearUpdate = true;
  105. // Write State.
  106. pStream->writeInt( mOrientationMode.Type, gOrientationTypeBits );
  107. switch ( mOrientationMode.Type )
  108. {
  109. case k_OrientationToPoint :
  110. {
  111. // Write Point.
  112. pStream->write( mOrientationMode.Point.x );
  113. pStream->write( mOrientationMode.Point.y );
  114. pStream->write( mOrientationMode.Point.z );
  115. } break;
  116. }
  117. if ( clearUpdate )
  118. {
  119. // Clear Update.
  120. state->Mask &= ~k_StateUpdateOrientation;
  121. }
  122. }
  123. // Return Mask.
  124. return retMask;
  125. }
  126. void VPathNode::unpackNode( NetConnection *pConnection, BitStream *pStream )
  127. {
  128. // Note: This is out of sync with VPathNode::packUpdate().
  129. // If you're ever going to use these methods outside of VPath, you
  130. // will need to read a flag *before* calling unpack!
  131. // Update World Data.
  132. bool updateWorld = false;
  133. // Update Local Position?
  134. if ( pStream->readFlag() )
  135. {
  136. // Read Local Position.
  137. pStream->read( &mLocalPosition.x );
  138. pStream->read( &mLocalPosition.y );
  139. pStream->read( &mLocalPosition.z );
  140. updateWorld = true;
  141. }
  142. // Update Local Rotation?
  143. if ( pStream->readFlag() )
  144. {
  145. // Read Local Rotation.
  146. pStream->read( &mLocalRotation.x );
  147. pStream->read( &mLocalRotation.y );
  148. pStream->read( &mLocalRotation.z );
  149. pStream->read( &mLocalRotation.w );
  150. updateWorld = true;
  151. }
  152. // Update Weight?
  153. if ( pStream->readFlag() )
  154. {
  155. // Read Weight.
  156. pStream->read( &mWeight );
  157. }
  158. // Update Orientation?
  159. if ( pStream->readFlag() )
  160. {
  161. // Read Orientation Mode.
  162. mOrientationMode.Type = ( eOrientationType )pStream->readInt( gOrientationTypeBits );
  163. switch ( mOrientationMode.Type )
  164. {
  165. case k_OrientationToPoint :
  166. {
  167. // Read Point.
  168. pStream->read( &mOrientationMode.Point.x );
  169. pStream->read( &mOrientationMode.Point.y );
  170. pStream->read( &mOrientationMode.Point.z );
  171. } break;
  172. }
  173. }
  174. if ( updateWorld )
  175. {
  176. // Update World Position.
  177. updateWorldData();
  178. }
  179. }
  180. String VPathNode::toString( void )
  181. {
  182. String retBuffer;
  183. // Buffer Node Properties.
  184. // {Position} {Rotation} {Weight}
  185. const AngAxisF aa( mLocalRotation );
  186. retBuffer = String::ToString( "%f %f %f %f %f %f %f %f", mLocalPosition.x, mLocalPosition.y, mLocalPosition.z,
  187. aa.axis.x, aa.axis.y, aa.axis.z, aa.angle,
  188. mWeight );
  189. // Add Tab.
  190. retBuffer += "\t";
  191. // Determine the Type.
  192. StringTableEntry typeString = getOrientationTypeLabel( mOrientationMode.Type );
  193. switch( mOrientationMode.Type )
  194. {
  195. case k_OrientationFree :
  196. {
  197. // Buffer String.
  198. retBuffer += typeString;
  199. } break;
  200. case k_OrientationToPoint:
  201. {
  202. // Fetch Point.
  203. const Point3F &lookAtPoint = mOrientationMode.Point;
  204. // Buffer String.
  205. retBuffer += String::ToString( "%s %f %f %f", typeString, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z );
  206. } break;
  207. }
  208. // Return String.
  209. return retBuffer;
  210. }
  211. bool VPathNode::fromString( const String &pString )
  212. {
  213. // Split Data.
  214. // {Position} {Rotation} {Weight}
  215. const char *baseData = StringUnit::getUnit( pString.c_str(), 0, "\t" );
  216. Point3F pos;
  217. AngAxisF aa;
  218. F32 weight;
  219. // Scan Base.
  220. dSscanf( baseData, "%g %g %g %g %g %g %g %g", &pos.x, &pos.y, &pos.z,
  221. &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle,
  222. &weight );
  223. // Apply Changes.
  224. setLocalPosition( pos );
  225. setLocalRotation( QuatF( aa ) );
  226. setWeight( weight );
  227. // Fetch Orientation Data.
  228. String orientationData = StringUnit::getUnit( pString.c_str(), 1, "\t" );
  229. // Fetch Orientation Type.
  230. String orientationTypeString = orientationData;
  231. if ( orientationData.find( " " ) )
  232. {
  233. // Use First Word.
  234. orientationTypeString = orientationData.substr( 0, orientationData.find( " " ) );
  235. }
  236. // Set Orientation Type.
  237. const eOrientationType &orientationType = getOrientationTypeEnum( orientationTypeString.c_str() );
  238. switch( orientationType )
  239. {
  240. case k_OrientationFree :
  241. {
  242. // Apply Mode.
  243. setOrientationMode( orientationType );
  244. } break;
  245. case k_OrientationToPoint:
  246. {
  247. // Fetch Point.
  248. Point3F lookAtPoint;
  249. // Buffer String.
  250. dSscanf( orientationData.c_str(), "%*s %f %f %f", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z );
  251. // Apply Mode.
  252. setOrientationMode( orientationType, lookAtPoint );
  253. } break;
  254. }
  255. return true;
  256. }
  257. //-----------------------------------------------------------------------------
  258. //
  259. // Property Methods.
  260. //
  261. //-----------------------------------------------------------------------------
  262. Point3F VPathNode::getWorldPosition( void ) const
  263. {
  264. return mWorldPosition;
  265. }
  266. QuatF VPathNode::getWorldRotation( void ) const
  267. {
  268. return mWorldRotation;
  269. }
  270. MatrixF VPathNode::getWorldTransform( void ) const
  271. {
  272. MatrixF mat;
  273. getWorldRotation().setMatrix( &mat );
  274. mat.setPosition( getWorldPosition() );
  275. return mat;
  276. }
  277. void VPathNode::setLocalPosition( const Point3F &pPosition )
  278. {
  279. // Update?
  280. if ( mLocalPosition != pPosition )
  281. {
  282. // Apply.
  283. mLocalPosition = pPosition;
  284. // Update World Position.
  285. updateWorldData();
  286. // Flag Update.
  287. setMaskBits( k_StateUpdatePosition );
  288. }
  289. }
  290. void VPathNode::setLocalRotation( const QuatF &pRotation )
  291. {
  292. // Update?
  293. if ( mLocalRotation != pRotation )
  294. {
  295. // Apply.
  296. mLocalRotation = pRotation;
  297. // Update World Rotation.
  298. updateWorldData();
  299. // Flag Update.
  300. setMaskBits( k_StateUpdateRotation );
  301. }
  302. }
  303. void VPathNode::setWeight( const F32 &pWeight )
  304. {
  305. // Update?
  306. if ( mWeight != pWeight )
  307. {
  308. // Apply.
  309. mWeight = pWeight;
  310. // Flag Update.
  311. setMaskBits( k_StateUpdateWeight );
  312. }
  313. }
  314. void VPathNode::setOrientationMode( const eOrientationType &pType )
  315. {
  316. // Update?
  317. if ( mOrientationMode.Type != pType )
  318. {
  319. // Update.
  320. mOrientationMode.Type = pType;
  321. // Flag Update.
  322. setMaskBits( k_StateUpdateOrientation );
  323. }
  324. }
  325. void VPathNode::setOrientationMode( const eOrientationType &pType, const Point3F &pPoint )
  326. {
  327. AssertFatal( pType == k_OrientationToPoint, "VPathNode::setOrientationMode() - Invalid mOrientation Type." );
  328. // Update?
  329. if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Point != pPoint ) )
  330. {
  331. // Update.
  332. mOrientationMode.Type = pType;
  333. mOrientationMode.Point = pPoint;
  334. // Flag Update.
  335. setMaskBits( k_StateUpdateOrientation );
  336. }
  337. }
  338. void VPathNode::updateWorldData( void )
  339. {
  340. if ( !mPath )
  341. {
  342. setWorldPosition( getLocalPosition() );
  343. setWorldRotation( getLocalRotation() );
  344. return;
  345. }
  346. // Fetch Path Details.
  347. const MatrixF &pathTransform = mPath->getTransform();
  348. const QuatF &pathRotation( pathTransform );
  349. // Calculate the World Position.
  350. Point3F newPosition = getLocalPosition();
  351. newPosition.convolve( mPath->getScale() );
  352. pathTransform.mulP( newPosition );
  353. // Calculate the new Rotation.
  354. QuatF newRotation;
  355. newRotation.mul( getLocalRotation(), pathRotation );
  356. // Apply.
  357. setWorldPosition( newPosition );
  358. setWorldRotation( newRotation );
  359. }
  360. //-----------------------------------------------------------------------------
  361. //
  362. // Enumeration Methods.
  363. //
  364. //-----------------------------------------------------------------------------
  365. // Implement the Orientation Type enum list.
  366. ImplementEnumType( VPathNodeOrientationType,"" )
  367. { VPathNode::k_OrientationFree, "FREE" },
  368. { VPathNode::k_OrientationToPoint, "TOPOINT" },
  369. EndImplementEnumType;
  370. VPathNode::eOrientationType VPathNode::getOrientationTypeEnum( const char *pLabel )
  371. {
  372. VPathNode::eOrientationType out;
  373. if ( !castConsoleTypeFromString( out, pLabel ) )
  374. {
  375. // Bah!
  376. return VPathNode::k_OrientationFree;
  377. }
  378. // Return.
  379. return out;
  380. }
  381. StringTableEntry VPathNode::getOrientationTypeLabel( const eOrientationType &pType )
  382. {
  383. // Return.
  384. return castConsoleTypeToString( pType );
  385. }