PageRenderTime 28ms CodeModel.GetById 36ms RepoModel.GetById 1ms app.codeStats 0ms

/Core/Dependencies/Engine/MultiplayerOnline/RakNet/PhysXGameObjectReplica.cpp

https://bitbucket.org/barakianc/nvidia-physx-and-apex-in-gge
C++ | 923 lines | 375 code | 113 blank | 435 comment | 49 complexity | 556693624b538a93c66a31bfa13c4842 MD5 | raw file
  1. #include "StdAfx.h"
  2. #ifdef PHYSX
  3. #include "PhysXGameObjectReplica.h"
  4. #include <string>
  5. #include <iostream>
  6. //#include "HavokNetManager.h"
  7. using namespace std;
  8. namespace GamePipeGame
  9. {
  10. ofstream outputLog;
  11. /// GameObjectReplica - Constructor
  12. GameObjectReplica::GameObjectReplica()
  13. : BasicReplica(),
  14. havokGameObject(NULL),
  15. m_sHKXFileName(""),
  16. m_eGameObjectType(0),
  17. angularVelocity(Ogre::Vector3::ZERO), realAngularVelocity(Ogre::Vector3::ZERO),
  18. sceneManager(NULL), owningManager(NULL),
  19. useServerPhysicsOnly(false),
  20. currentAnimation("None")
  21. {
  22. }
  23. /// GameObjectReplica - Constructor
  24. ///
  25. /// Parameters:
  26. /// newName - a name for this object. Does not have to be unique.
  27. /// newMesh - the filename of the mesh for this object. Default value is empty.
  28. /// newEntity - an entity name for this object, which would likely be determined later anyway. Default value is empty.
  29. /// newMass - a value for an object's weight. Default value is zero.
  30. GameObjectReplica::GameObjectReplica(Ogre::String newName, Ogre::String newMesh, Ogre::String newEntity, Ogre::Real newMass)
  31. : BasicReplica(newName, newMesh, newEntity, newMass),
  32. havokGameObject(NULL),
  33. m_sHKXFileName(""),
  34. m_eGameObjectType(0),
  35. angularVelocity(Ogre::Vector3::ZERO), realAngularVelocity(Ogre::Vector3::ZERO),
  36. sceneManager(NULL), owningManager(NULL),
  37. useServerPhysicsOnly(false),
  38. currentAnimation("None")
  39. {
  40. }
  41. /// ~GameObjectReplica - Destructor
  42. ///
  43. /// This function also cleans up associated Havok objects and further associated Ogre objects created by said Havok objects.
  44. GameObjectReplica::~GameObjectReplica()
  45. {
  46. // We have to do a little cleanup first before this replica can be destroyed
  47. // properly (because the Havok object doesn't pick up after itself...)
  48. //
  49. // 1. Remove the reference to the havok object from the havok world
  50. // 2. Remove the havok object from the GameObjectManager's list
  51. // 3. Remove the Ogre entity and its parent scene node from the scene.
  52. if(havokGameObject != NULL && owningManager != NULL)
  53. {
  54. owningManager->RemoveGameObject(havokGameObject);
  55. }
  56. else
  57. cout << "[GameObjectReplica/destructor] Could not remove havok information, as there was no valid GameObject or GameObjectManager pointer." << endl;
  58. if(sceneManager != NULL)
  59. {
  60. Ogre::Entity *entity = sceneManager->getEntity(entityName);
  61. if(entity != NULL)
  62. {
  63. Ogre::SceneNode *sceneNode = entity->getParentSceneNode();
  64. if(sceneNode != NULL) sceneManager->destroySceneNode(sceneNode);
  65. sceneManager->destroyEntity(entity);
  66. }
  67. else
  68. {
  69. cout << "[GameObjectReplica/destructor] Could not destroy Ogre scene information, as " << entityName << " could not be found." << endl;
  70. }
  71. }
  72. }
  73. /// GetName - Returns a print out of a name, suitable for framing. Virtual, redefined from GameObjectReplica.
  74. RakNet::RakString
  75. GameObjectReplica::GetName() const
  76. {
  77. Ogre::String ogreString = "Class: GameObjectReplica, Name: ";
  78. ogreString += objName;
  79. return RakNet::RakString(ogreString.c_str());
  80. }
  81. /// WriteAllocationID - Writes a unique string to be used by the replica factory. Virtual, redefined from GameObjectReplica.
  82. ///
  83. /// Parameters:
  84. /// allocationIdBitstream - a RakNet BitStream where the allocation string will be written to (and later read from by the factory)
  85. void
  86. GameObjectReplica::WriteAllocationID(RakNet::Connection_RM3 *destinationConnection, RakNet::BitStream *allocationIdBitstream) const
  87. {
  88. Ogre::String className = "GameObjectReplica";
  89. allocationIdBitstream->Write(className.c_str());
  90. }
  91. /// SerializeConstruction - Serializes data for a remote object reference/creation call.
  92. /// Virtual, redefined from GameObjectReplica.
  93. ///
  94. /// Parameters:
  95. /// constructionBitstream - a RakNet BitStream containing the data to be used in the object's remote construction
  96. /// destinationConnection - the connection the remote object will be created on (in case special serialization is needed)
  97. void
  98. GameObjectReplica::SerializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *destinationConnection)
  99. {
  100. constructionBitstream->Write(GetName() + RakNet::RakString(" SerializeConstruction"));
  101. constructionBitstream->Write(RakNet::RakString(objName.c_str()));
  102. constructionBitstream->Write(RakNet::RakString(meshName.c_str()));
  103. constructionBitstream->Write(RakNet::RakString(m_sHKXFileName.c_str()));
  104. constructionBitstream->Write(mass);
  105. constructionBitstream->Write((int)m_eGameObjectType);
  106. constructionBitstream->Write(position.x);
  107. constructionBitstream->Write(position.y);
  108. constructionBitstream->Write(position.z);
  109. constructionBitstream->Write(orientation.x);
  110. constructionBitstream->Write(orientation.y);
  111. constructionBitstream->Write(orientation.z);
  112. constructionBitstream->Write(orientation.w);
  113. constructionBitstream->Write(velocity.x);
  114. constructionBitstream->Write(velocity.y);
  115. constructionBitstream->Write(velocity.z);
  116. constructionBitstream->Write(angularVelocity.x);
  117. constructionBitstream->Write(angularVelocity.y);
  118. constructionBitstream->Write(angularVelocity.z);
  119. //@Animation
  120. constructionBitstream->Write(RakNet::RakString(currentAnimation.c_str()));
  121. if(topology == SERVER)
  122. {
  123. entityName = objName;
  124. entityName.append(".");
  125. //entityName.append(Ogre::StringConverter::toString((int)GetNetworkID().localSystemAddress));
  126. // raknet 4.0b8
  127. entityName.append(Ogre::StringConverter::toString((int)GetNetworkID()));
  128. }
  129. else
  130. {
  131. }
  132. }
  133. /// DeserializeConstruction - Reads and processes incoming data from a remote object reference/creation call.
  134. /// Virtual, redefined from GameObjectReplica.
  135. ///
  136. /// Parameters:
  137. /// constructionBitstream - a RakNet BitStream containing the data to be used in the object's remote construction
  138. /// sourceConnection - the connection calling for the construction of the object represented by this replica
  139. bool
  140. GameObjectReplica::DeserializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *sourceConnection)
  141. {
  142. RakNet::RakString rakString;
  143. RakNet::RakString rakStringObjectName;
  144. RakNet::RakString rakStringMeshName;
  145. RakNet::RakString rakStringHavokObjectFileName;
  146. RakNet::RakString rakStringHavokObjectModelName;
  147. Ogre::Real initialMass;
  148. int initialHavokObjectType; //initialHavokObjectSubType;
  149. Ogre::Vector3 initialPosition, initialVelocity, initialAngularVelocity;
  150. Ogre::Quaternion initialOrientation;
  151. constructionBitstream->Read(rakString);
  152. constructionBitstream->Read(rakStringObjectName);
  153. constructionBitstream->Read(rakStringMeshName);
  154. constructionBitstream->Read(rakStringHavokObjectFileName);
  155. //constructionBitstream->Read(rakStringHavokObjectModelName);
  156. constructionBitstream->Read(initialMass);
  157. constructionBitstream->Read(initialHavokObjectType);
  158. //constructionBitstream->Read(initialHavokObjectSubType);
  159. constructionBitstream->Read(initialPosition.x);
  160. constructionBitstream->Read(initialPosition.y);
  161. constructionBitstream->Read(initialPosition.z);
  162. constructionBitstream->Read(initialOrientation.x);
  163. constructionBitstream->Read(initialOrientation.y);
  164. constructionBitstream->Read(initialOrientation.z);
  165. constructionBitstream->Read(initialOrientation.w);
  166. constructionBitstream->Read(initialVelocity.x);
  167. constructionBitstream->Read(initialVelocity.y);
  168. constructionBitstream->Read(initialVelocity.z);
  169. constructionBitstream->Read(initialAngularVelocity.x);
  170. constructionBitstream->Read(initialAngularVelocity.y);
  171. constructionBitstream->Read(initialAngularVelocity.z);
  172. //@Animation
  173. RakNet::RakString rakAnimationString;
  174. constructionBitstream->Read(rakAnimationString);
  175. currentAnimation = rakAnimationString.C_String();
  176. objName = rakStringObjectName.C_String();
  177. meshName = rakStringMeshName.C_String();
  178. m_sHKXFileName = rakStringHavokObjectFileName.C_String();
  179. mass = initialMass;
  180. m_eGameObjectType = initialHavokObjectType;
  181. position = realPosition = initialPosition;
  182. orientation = realOrientation = initialOrientation;
  183. velocity = realVelocity = initialVelocity;
  184. angularVelocity = realAngularVelocity = initialAngularVelocity;
  185. if(topology == CLIENT)
  186. {
  187. entityName = objName;
  188. entityName.append(".");
  189. //entityName.append(Ogre::StringConverter::toString((int)GetNetworkID().localSystemAddress));
  190. //raknet 4.0b8
  191. entityName.append(Ogre::StringConverter::toString((int)GetNetworkID()));
  192. }
  193. else
  194. {
  195. }
  196. return true;
  197. }
  198. /// DeallocReplica - Determines what should be done when a replica should be deleted. Virtual, redefined from GameObjectReplica.
  199. ///
  200. /// Parameters:
  201. /// sourceConnection - the connection calling for the destruction of the object represented by this replica
  202. void
  203. GameObjectReplica::DeallocReplica(RakNet::Connection_RM3 *sourceConnection)
  204. {
  205. // RMF deleting the object here consistently causes a crash having to do with m_pGraphicsObject.
  206. //delete this;
  207. }
  208. /// Serialize - Writes data to a Bitstream to be sent to a remote system. Virtual, redefined from GameObjectReplica.
  209. ///
  210. /// If allowed to by the returned result of QuerySerialize, this function runs every call to replicaManager->Update(),
  211. /// for every object, for every connection.
  212. ///
  213. /// Parameters:
  214. /// serializeParameters - a RakNet SerializeParameters class containing the serialized information to be sent
  215. RakNet::RM3SerializationResult
  216. GameObjectReplica::Serialize(RakNet::SerializeParameters *serializeParameters)
  217. {
  218. // If we are a client:
  219. // 1. If this replica is flagged to use server physics, we don't serialize this (might need to move this to QuerySerialize)
  220. // 2. If this object has not been flagged as modified AND it's been less than 1ms since the last update, we don't serialize
  221. // Otherwise, reset the client-modified flag and serialize normally
  222. if(topology1 == CLIENT)
  223. {
  224. if(useServerPhysicsOnly) return RakNet::RM3SR_DO_NOT_SERIALIZE;
  225. /*RakNetTime diffUpdateTime = RakNet::GetTime() - lastUpdateClient;*/
  226. //raknet 4.0b8
  227. RakNet::Time diffUpdateTime = RakNet::GetTime() - lastUpdateClient;
  228. if(!clientModified && ( (RakNet::GetTime() - lastUpdateClient) < 1000) )
  229. {
  230. // cout << "[GameObjectReplica/Serialize] CLIENT: no local modification, should skip serialization this tick" << endl;
  231. return RakNet::RM3SR_DO_NOT_SERIALIZE;
  232. }
  233. else
  234. {
  235. // cout << "[GameObjectReplica/Serialize] CLIENT: locally modified, should serialize to server and reset modification flag" << endl;
  236. clientModified = false;
  237. }
  238. }
  239. /*RakNetTime time = RakNet::GetTime()/1000;*/
  240. //raknet 4.0b8
  241. RakNet::Time time = RakNet::GetTime()/1000;
  242. serializeParameters->outputBitstream[0].Write(time);
  243. serializeParameters->outputBitstream[0].Write(position.x);
  244. serializeParameters->outputBitstream[0].Write(position.y);
  245. serializeParameters->outputBitstream[0].Write(position.z);
  246. serializeParameters->outputBitstream[0].Write(realPosition.x);
  247. serializeParameters->outputBitstream[0].Write(realPosition.y);
  248. serializeParameters->outputBitstream[0].Write(realPosition.z);
  249. serializeParameters->outputBitstream[0].Write(orientation.x);
  250. serializeParameters->outputBitstream[0].Write(orientation.y);
  251. serializeParameters->outputBitstream[0].Write(orientation.z);
  252. serializeParameters->outputBitstream[0].Write(orientation.w);
  253. serializeParameters->outputBitstream[0].Write(realOrientation.x);
  254. serializeParameters->outputBitstream[0].Write(realOrientation.y);
  255. serializeParameters->outputBitstream[0].Write(realOrientation.z);
  256. serializeParameters->outputBitstream[0].Write(realOrientation.w);
  257. serializeParameters->outputBitstream[0].Write(velocity.x);
  258. serializeParameters->outputBitstream[0].Write(velocity.y);
  259. serializeParameters->outputBitstream[0].Write(velocity.z);
  260. serializeParameters->outputBitstream[0].Write(realVelocity.x);
  261. serializeParameters->outputBitstream[0].Write(realVelocity.y);
  262. serializeParameters->outputBitstream[0].Write(realVelocity.z);
  263. serializeParameters->outputBitstream[0].Write(angularVelocity.x);
  264. serializeParameters->outputBitstream[0].Write(angularVelocity.y);
  265. serializeParameters->outputBitstream[0].Write(angularVelocity.z);
  266. serializeParameters->outputBitstream[0].Write(realAngularVelocity.x);
  267. serializeParameters->outputBitstream[0].Write(realAngularVelocity.y);
  268. serializeParameters->outputBitstream[0].Write(realAngularVelocity.z);
  269. //@Animation
  270. //Note entering here since no string entered here
  271. serializeParameters->outputBitstream[0].Write(RakNet::RakString(currentAnimation.c_str()));
  272. // set a non-zero value so the timestamp is passed
  273. serializeParameters->messageTimestamp = RakNet::GetTime();
  274. // update the appropriate timestamp for the source of this update (can be used later for interpolation)
  275. if(topology == CLIENT)
  276. lastUpdateClient = RakNet::GetTime();
  277. else
  278. lastUpdateServer = RakNet::GetTime();
  279. return RakNet::RM3SR_BROADCAST_IDENTICALLY;
  280. }
  281. /// Deserialize - Reads and processes incoming data from a remote serialization.
  282. /// Virtual, redefined from GameObjectReplica.
  283. ///
  284. /// Parameters:
  285. /// deserializeParameters - a RakNet DeserializeParameters class containing the serialized information to be read
  286. void
  287. GameObjectReplica::Deserialize(RakNet::DeserializeParameters *deserializeParameters)
  288. {
  289. //RakNetTime dsTime;
  290. //raknet 4.0b8
  291. RakNet::Time dsTime;
  292. Ogre::Vector3 newPosition, newRealPosition;
  293. Ogre::Quaternion newOrientation, newRealOrientation;
  294. Ogre::Vector3 newVelocity, newRealVelocity;
  295. Ogre::Vector3 newAngularVelocity, newRealAngularVelocity;
  296. // Read in the values from the serialization string here. The order has to match the original serialization order.
  297. deserializeParameters->serializationBitstream[0].Read(dsTime);
  298. deserializeParameters->serializationBitstream[0].Read(newPosition.x);
  299. deserializeParameters->serializationBitstream[0].Read(newPosition.y);
  300. deserializeParameters->serializationBitstream[0].Read(newPosition.z);
  301. deserializeParameters->serializationBitstream[0].Read(newRealPosition.x);
  302. deserializeParameters->serializationBitstream[0].Read(newRealPosition.y);
  303. deserializeParameters->serializationBitstream[0].Read(newRealPosition.z);
  304. deserializeParameters->serializationBitstream[0].Read(newOrientation.x);
  305. deserializeParameters->serializationBitstream[0].Read(newOrientation.y);
  306. deserializeParameters->serializationBitstream[0].Read(newOrientation.z);
  307. deserializeParameters->serializationBitstream[0].Read(newOrientation.w);
  308. deserializeParameters->serializationBitstream[0].Read(newRealOrientation.x);
  309. deserializeParameters->serializationBitstream[0].Read(newRealOrientation.y);
  310. deserializeParameters->serializationBitstream[0].Read(newRealOrientation.z);
  311. deserializeParameters->serializationBitstream[0].Read(newRealOrientation.w);
  312. deserializeParameters->serializationBitstream[0].Read(newVelocity.x);
  313. deserializeParameters->serializationBitstream[0].Read(newVelocity.y);
  314. deserializeParameters->serializationBitstream[0].Read(newVelocity.z);
  315. deserializeParameters->serializationBitstream[0].Read(newRealVelocity.x);
  316. deserializeParameters->serializationBitstream[0].Read(newRealVelocity.y);
  317. deserializeParameters->serializationBitstream[0].Read(newRealVelocity.z);
  318. deserializeParameters->serializationBitstream[0].Read(newAngularVelocity.x);
  319. deserializeParameters->serializationBitstream[0].Read(newAngularVelocity.y);
  320. deserializeParameters->serializationBitstream[0].Read(newAngularVelocity.z);
  321. deserializeParameters->serializationBitstream[0].Read(newRealAngularVelocity.x);
  322. deserializeParameters->serializationBitstream[0].Read(newRealAngularVelocity.y);
  323. deserializeParameters->serializationBitstream[0].Read(newRealAngularVelocity.z);
  324. //@Animation
  325. RakNet::RakString rakAnimationString;
  326. deserializeParameters->serializationBitstream[0].Read(rakAnimationString);
  327. currentAnimation = rakAnimationString.C_String();
  328. // Now that we have all of the serialized values from the update, we have to determine what to do with them.
  329. // If we are the server:
  330. // 1. Set the last client update time (this can be used later for extrapolation)
  331. // 2. Check the values for validity. There's no real checking done below, and so we accept the values as valid by default
  332. // If the value(s) are valid:
  333. // 1. Set the "local" and the server-side values to the client-requested values
  334. // 2. Update the rigid body information with this new update so it can be processed by the Havok world later
  335. if(topology == SERVER)
  336. {
  337. lastUpdateClient = RakNet::GetTime();
  338. if(true) // sanity check the position update sent from the client
  339. {
  340. position = realPosition = newPosition;
  341. orientation = realOrientation = newOrientation;
  342. velocity = realVelocity = newVelocity;
  343. angularVelocity = realAngularVelocity = newAngularVelocity;
  344. //if(havokGameObject != NULL) SetHavokRigidBodyInfo(position, orientation, velocity, angularVelocity);
  345. }
  346. else
  347. serverCorrected = true;
  348. }
  349. else
  350. {
  351. // Otherwise, this is a client:
  352. // 1. Set the last server update time (this can be used later for extrapolation)
  353. // 2. If the update from the server is different than the last update (the values currently stored in the real* variables):
  354. // If this object is a keyframed object, we only copy the position and orientation values.
  355. // Otherwise, this is a normal object and:
  356. // 1. Update the server values with the latest values from the server
  357. // 2. Update the client-side positions only if the server update is outside of a specific range, or we don't own this object
  358. lastUpdateServer = RakNet::GetTime();
  359. if(realPosition != newRealPosition || realOrientation != newRealOrientation || velocity != newRealVelocity || angularVelocity != newAngularVelocity)
  360. {
  361. if(m_eGameObjectType == PHYSICS_KEYFRAMED)
  362. {
  363. position = realPosition = newPosition;
  364. orientation = realOrientation = newOrientation;
  365. velocity = realVelocity = Ogre::Vector3::ZERO;
  366. angularVelocity = realAngularVelocity = Ogre::Vector3::ZERO;
  367. }
  368. else
  369. {
  370. realPosition = newRealPosition;
  371. realOrientation = newRealOrientation;
  372. realVelocity = newRealVelocity;
  373. realAngularVelocity = newRealAngularVelocity;
  374. if(position.squaredDistance(realPosition) > 1 || !orientation.equals(realOrientation, Ogre::Radian((Ogre::Real)0.1475)) ||
  375. //creatingSystemGUID != replicaManager->GetRakPeerInterface()->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS))
  376. //raknet 4.0b8
  377. creatingSystemGUID != replicaManager->GetRakPeerInterface()->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS))
  378. {
  379. // This section would probably be better done by using lerp for position and slerp for orientation instead of direct copy
  380. position = realPosition;
  381. orientation = realOrientation;
  382. velocity = realVelocity;
  383. angularVelocity = realAngularVelocity;
  384. }
  385. }
  386. // update the rigid body information with the correctly updated information
  387. //if(havokGameObject != NULL) SetHavokRigidBodyInfo(position, orientation, velocity, angularVelocity);
  388. // flag to indicate this was corrected by the server, might be vestigial now
  389. serverCorrected = true;
  390. }
  391. }
  392. }
  393. /* Havok-related functions */
  394. /// GetHavokGameObject - Sets a pointer to the Havok GameObject associated with this replica
  395. /*void GameObjectReplica::SetHavokGameObject(GameObject *newHavokGameObject) {havokGameObject = newHavokGameObject; }
  396. /// GetHavokObjectFileName - Sets the filename where the object's Havok information is stored (eg., "object.hkx")
  397. void GameObjectReplica::SetHavokObjectFileName(const char *newHavokObjectFileName) { m_sHKXFileName = newHavokObjectFileName; }
  398. void
  399. GameObjectReplica::SetHavokObjectFileInfo(const char *newHavokObjectFileName, const char *newMeshName)
  400. {
  401. SetHavokObjectFileName(newHavokObjectFileName);
  402. SetMeshName(newMeshName);
  403. }
  404. /// SetHavokObjectType - Sets an object's primary Havok type (GameObjectType)
  405. void GameObjectReplica::SetHavokObjectType(int newHavokObjectType) { m_eGameObjectType = newHavokObjectType; }*/
  406. /// SetAngularVelocity - Sets the local value for an object's angular velocity. Uses 3 floats.
  407. void GameObjectReplica::SetAngularVelocity(float x, float y, float z) { angularVelocity = Ogre::Vector3(x, y, z); }
  408. /// SetAngularVelocity - Sets the local value for an object's angular velocity. Uses a Vector3.
  409. void GameObjectReplica::SetAngularVelocity(Ogre::Vector3 newAngularVelocity) { angularVelocity = newAngularVelocity; }
  410. /// SetRealAngularVelocity - Sets the server's last updated value for an object's angular velocity. Uses 3 floats.
  411. void GameObjectReplica::SetRealAngularVelocity(float x, float y, float z) { realAngularVelocity = Ogre::Vector3(x, y, z); }
  412. /// SetRealAngularVelocity - Sets the server's last updated value for an object's angular velocity. Uses a Vector3.
  413. void GameObjectReplica::SetRealAngularVelocity(Ogre::Vector3 newRealAngularVelocity) { realAngularVelocity = newRealAngularVelocity; }
  414. /// GetHavokGameObject - Gets a pointer to the Havok GameObject associated with this replica
  415. /*GameObject * GameObjectReplica::GetHavokGameObject() { return havokGameObject; }
  416. /// GetHavokObjectFileName - Gets the filename where the object's Havok information is stored (eg., "object.hkx")
  417. Ogre::String GameObjectReplica::GetHavokObjectFileName() { return m_sHKXFileName; }
  418. /// GetHavokObjectType - Gets an object's primary Havok type (GameObjectType)
  419. GameObjectType GameObjectReplica::GetHavokObjectType() { return static_cast<GameObjectType>(m_eGameObjectType); }*/
  420. /// GetAngularVelocity - Gets the local value for an object's angular velocity.
  421. Ogre::Vector3 GameObjectReplica::GetAngularVelocity() { return angularVelocity; }
  422. /// GetRealAngularVelocity - Gets the server's last updated value for an object's angular velocity.
  423. Ogre::Vector3 GameObjectReplica::GetRealAngularVelocity() { return realAngularVelocity; }
  424. /// GetHavokRigidBodyInfo - Copies spatial and physics information from a Havok GameObject
  425. ///
  426. /// This function accounts for the different Havok object types.
  427. ///
  428. /// Parameters:
  429. /// hkPosition - a reference to a Havok position vector
  430. /// hkVelocity - a reference to a Havok velocity vector
  431. /// hkAngularVelocity - a reference to a Havok angular velocity vector
  432. /// hkOrientation - a reference to a Havok orientation quaternion
  433. /*void
  434. GameObjectReplica::GetHavokRigidBodyInfo(hkVector4 &hkPosition, hkVector4 &hkVelocity, hkVector4 &hkAngularVelocity, hkQuaternion &hkOrientation)
  435. {
  436. hkPosition.set(0, 0, 0);
  437. hkVelocity.set(0, 0, 0);
  438. hkAngularVelocity.set(0, 0, 0);
  439. hkOrientation.m_vec.set(0, 0, 0, 1);
  440. // The raw spatial information is available through different sources depending on the Havok object type
  441. // Here we have to differentiate between the following Havok types:
  442. // 1. {CHARACTER, CHARACTER_RIGIDBODY) - information is available through the CharacterRigidBodyObject->hkpRigidBody pointer
  443. // 2. {CHARACTER, CHARACTER_PROXY} - only position and velocity information is available, orientation/angular velocity not supported
  444. // 3. {PHYSICS, *} - information is available through the PhysicsObject->hkpRigidBody pointer
  445. if ((havokGameObject->m_eObjectType == ANIMATED_CHARACTER_RIGIDBODY)||(havokGameObject->m_eObjectType == PHYSICS_CHARACTER_RIGIDBODY))
  446. {
  447. CharacterRigidBodyObject *crbo = static_cast<CharacterRigidBodyObject *>(havokGameObject->m_pPhysicsObject);
  448. hkPosition = crbo->getCharacterRigidBody()->getRigidBody()->getPosition();
  449. hkVelocity = crbo->getCharacterRigidBody()->getRigidBody()->getLinearVelocity();
  450. hkAngularVelocity = crbo->getCharacterRigidBody()->getRigidBody()->getAngularVelocity();
  451. hkOrientation = crbo->getCharacterRigidBody()->getRigidBody()->getRotation();
  452. }
  453. else if((havokGameObject->m_eObjectType == ANIMATED_CHARACTER_PROXY)||(havokGameObject->m_eObjectType == PHYSICS_CHARACTER_PROXY))
  454. {
  455. CharacterProxyObject *cpo = static_cast<CharacterProxyObject *>(havokGameObject->m_pPhysicsObject);
  456. hkPosition = cpo->getCharacterProxy()->getPosition();
  457. hkVelocity = cpo->getCharacterProxy()->getLinearVelocity();
  458. }
  459. else
  460. {
  461. Ogre::Vector3 gameObjectPosition = havokGameObject->getPosition();
  462. hkPosition = hkVector4(gameObjectPosition.x,gameObjectPosition.y,gameObjectPosition.z);
  463. PhysicsPrimitiveObject* f_pTempObject = (PhysicsPrimitiveObject*)havokGameObject->m_pPhysicsObject;
  464. if (f_pTempObject!=NULL)
  465. {
  466. hkOrientation = f_pTempObject->getRigidBody()->getRotation();
  467. hkVelocity = f_pTempObject->getRigidBody()->getLinearVelocity();
  468. hkAngularVelocity = f_pTempObject->getRigidBody()->getAngularVelocity();
  469. }
  470. else//this should be fixed, functions should be added to PhysicsObject and all children under it
  471. { hkOrientation = hkQuaternion(0,0,0,1);
  472. hkVelocity = hkVector4(0,0,0);
  473. hkAngularVelocity = hkVector4(0,0,0);
  474. }
  475. }
  476. }
  477. /// SetHavokRigidBodyInfo - Copies spatial and physics information into a Havok GameObject
  478. ///
  479. /// This function converts Ogre data types to Havok data types and accounts for the different Havok object types.
  480. ///
  481. /// Parameters:
  482. /// updatePosition - a new position vector
  483. /// updateOrientation - a new orientation quaternion
  484. /// updateVelocity - a new velocity vector
  485. /// updateAngularVelocity - a new angular velocity vector
  486. void
  487. GameObjectReplica::SetHavokRigidBodyInfo(Ogre::Vector3 updatePosition, Ogre::Quaternion updateOrientation, Ogre::Vector3 updateVelocity, Ogre::Vector3 updateAngularVelocity)
  488. {
  489. hkVector4 newPosition, newVelocity, newAngularVelocity;
  490. hkQuaternion newOrientation;
  491. newPosition.set(updatePosition.x, updatePosition.y, updatePosition.z);
  492. newVelocity.set(updateVelocity.x, updateVelocity.y, updateVelocity.z);
  493. newAngularVelocity.set(updateAngularVelocity.x, updateAngularVelocity.y, updateAngularVelocity.z);
  494. newOrientation.m_vec.set(updateOrientation.x, updateOrientation.y, updateOrientation.z, updateOrientation.w);
  495. if((havokGameObject->m_eObjectType == ANIMATED_CHARACTER_RIGIDBODY)||(havokGameObject->m_eObjectType == PHYSICS_CHARACTER_RIGIDBODY))
  496. {
  497. CharacterRigidBodyObject *crbo = dynamic_cast<CharacterRigidBodyObject *>(havokGameObject->m_pPhysicsObject);
  498. crbo->getCharacterRigidBody()->getRigidBody()->setPosition(newPosition);
  499. crbo->getCharacterRigidBody()->getRigidBody()->setRotation(newOrientation);
  500. crbo->getCharacterRigidBody()->getRigidBody()->setLinearVelocity(newVelocity);
  501. crbo->getCharacterRigidBody()->getRigidBody()->setAngularVelocity(newAngularVelocity);
  502. }
  503. else if((havokGameObject->m_eObjectType == ANIMATED_CHARACTER_PROXY)||(havokGameObject->m_eObjectType == PHYSICS_CHARACTER_PROXY))
  504. {
  505. CharacterProxyObject *cpo = static_cast<CharacterProxyObject *>(havokGameObject->m_pPhysicsObject);
  506. cpo->getCharacterProxy()->setPosition(newPosition);
  507. cpo->getCharacterProxy()->setLinearVelocity(newVelocity);
  508. }
  509. else
  510. {
  511. havokGameObject->setPosition(updatePosition.x,updatePosition.y,updatePosition.z);
  512. PhysicsPrimitiveObject* f_pTempObject = (PhysicsPrimitiveObject*)havokGameObject->m_pPhysicsObject;
  513. if (f_pTempObject!=NULL)
  514. {
  515. f_pTempObject->getRigidBody()->setRotation(newOrientation);
  516. f_pTempObject->getRigidBody()->setLinearVelocity(newVelocity);
  517. f_pTempObject->getRigidBody()->setAngularVelocity(newAngularVelocity);
  518. }
  519. else
  520. {
  521. //do we need to set these parameters unless the object is physics primitive??
  522. //this should be fixed, functions should be added to PhysicsObject and all children under it
  523. }
  524. }
  525. }*/
  526. /// playAnimation - Play animation on GameObject for this replica
  527. /// Parameters: animationName - Name of animation to be played
  528. ///
  529. /// Returns: Nothing.
  530. void GameObjectReplica::playAnimation(Ogre::String animationName)
  531. {
  532. if(havokGameObject==NULL)
  533. {
  534. //try finding
  535. Ogre::String objectName = GetObjectName();
  536. Ogre::String newEntityName = objectName + ".";
  537. newEntityName.append(Ogre::StringConverter::toString((int)(GetNetworkID())));
  538. GameObject *hgameobject = GetGameObjectManager()->GetGameObject(newEntityName);
  539. if(hgameobject==NULL)
  540. return;
  541. else
  542. havokGameObject = hgameobject;
  543. }
  544. if(hasAnimation(animationName))
  545. {
  546. havokGameObject->m_pAnimatedEntity->StopAnimation();
  547. havokGameObject->PlayAnimation(animationName);
  548. currentAnimation = animationName;
  549. return;
  550. }
  551. else
  552. {
  553. currentAnimation="None";
  554. stopAnimation();
  555. }
  556. }
  557. /// stopAnimation - Stop animation on GameObject for this replica. If no name is specified, stops all animations
  558. /// Parameters: animationName - Name of animation to be stopeed
  559. ///
  560. /// Returns: Nothing.
  561. void GameObjectReplica::stopAnimation(Ogre::String animationName)
  562. {
  563. if(havokGameObject==NULL)
  564. {
  565. //try finding
  566. Ogre::String objectName = GetObjectName();
  567. Ogre::String newEntityName = objectName + ".";
  568. newEntityName.append(Ogre::StringConverter::toString((int)(GetNetworkID())));
  569. GameObject *hgameobject = GetGameObjectManager()->GetGameObject(newEntityName);
  570. if(hgameobject==NULL)
  571. return;
  572. else
  573. havokGameObject = hgameobject;
  574. }
  575. if(animationName=="")
  576. {
  577. currentAnimation="None";
  578. havokGameObject->m_pAnimatedEntity->StopAnimation();
  579. }
  580. else if(currentAnimation==animationName)
  581. {
  582. currentAnimation="None";
  583. havokGameObject->m_pAnimatedEntity->StopAnimation();
  584. }
  585. else
  586. return;
  587. }
  588. /// hasAnimation - Returns whether or not replica has an animation or not
  589. /// Parameters: animationName - Name of animation to be queried
  590. ///
  591. /// Returns: bool depending on animation found or not
  592. bool GameObjectReplica::hasAnimation(Ogre::String animationName)
  593. {
  594. if(havokGameObject==NULL)
  595. {
  596. //try finding
  597. Ogre::String objectName = GetObjectName();
  598. Ogre::String newEntityName = objectName + ".";
  599. newEntityName.append(Ogre::StringConverter::toString((int)(GetNetworkID())));
  600. GameObject *hgameobject = GetGameObjectManager()->GetGameObject(newEntityName);
  601. if(hgameobject==NULL)
  602. return false;
  603. else
  604. havokGameObject = hgameobject;
  605. }
  606. if(havokGameObject->HasAnimationName(animationName))
  607. return true;
  608. return false;
  609. }
  610. /// ProcessHavokStep - Processes an object after a previous Havok world simulation step.
  611. ///
  612. /// Using this information, a server can determine whether it should send out an update for an object it's responsible for.
  613. /// A client will be able to use this function to determine whether it should send its own update, or rollback changes made
  614. /// by its local physics world.
  615. ///
  616. /// Parameters: isOwner - a flag indicating whether the GUID of the system creating the replica matches the GUID of this system
  617. ///
  618. /// Returns: Nothing. A call to this function when a Havok GameObject does not exist will simply return.
  619. /*void
  620. GameObjectReplica::ProcessHavokStep(bool isOwner,NetTopology topology)
  621. {
  622. // If there's no associated Havok GameObject, then there's no point in updating.
  623. if(havokGameObject == NULL) return;
  624. AnimationManager::AnimatedEntity *animatedEntity = havokGameObject->m_pAnimatedEntity;
  625. if(animatedEntity!=NULL)
  626. {
  627. if(topology == SERVER)
  628. {
  629. // isanimationplaying not working with havok animation so cant use server update
  630. }
  631. else
  632. {
  633. if(currentAnimation=="None")
  634. {
  635. animatedEntity->StopAnimation();
  636. }
  637. else if(animatedEntity->HasAnimationName(currentAnimation) && currentAnimation!=animatedEntity->GetActiveAnimation())
  638. {
  639. if((m_sHKXFileName=="" && !animatedEntity->IsAnimationPlaying(currentAnimation.c_str())))
  640. havokGameObject->PlayAnimation(currentAnimation);
  641. else if(m_sHKXFileName.length() > 0)
  642. {
  643. animatedEntity->StopAnimation();
  644. havokGameObject->PlayAnimation(currentAnimation);
  645. }
  646. }
  647. else if(animatedEntity->HasAnimationName(currentAnimation))
  648. {
  649. //do nothing
  650. }
  651. else
  652. {
  653. animatedEntity->StopAnimation();
  654. }
  655. }
  656. }
  657. if(havokGameObject->m_eObjectType==GRAPHICS_OBJECT)
  658. {
  659. velocity = realVelocity = Ogre::Vector3(0,0,0);
  660. angularVelocity = realAngularVelocity = Ogre::Vector3(0,0,0);
  661. if(topology == SERVER)
  662. {
  663. position = realPosition = havokGameObject->getPosition();
  664. serverCorrected = true;
  665. }
  666. else
  667. {
  668. if(useServerPhysicsOnly)
  669. {
  670. position = realPosition;
  671. havokGameObject->setPosition(realPosition.x,realPosition.y,realPosition.z);
  672. }
  673. else
  674. {
  675. clientModified = true;
  676. }
  677. }
  678. return;
  679. }
  680. // Now that the simulation has taken a step, we update the "real" values. If the "real" value is different
  681. // than the previous value, it has been effectively modified and and it should be serialized to the server/client
  682. hkVector4 postHavokPosition, postHavokVelocity, postHavokAngularVelocity;
  683. hkQuaternion postHavokOrientation;
  684. if(havokGameObject->m_eObjectType!=GRAPHICS_OBJECT)
  685. GetHavokRigidBodyInfo(postHavokPosition, postHavokVelocity, postHavokAngularVelocity, postHavokOrientation);
  686. // For readability, I'm converting the Havok types to Ogre types
  687. Ogre::Vector3 postHavokPositionV3 = Ogre::Vector3(postHavokPosition.getQuad().v[0], postHavokPosition.getQuad().v[1], postHavokPosition.getQuad().v[2]);
  688. Ogre::Vector3 postHavokVelocityV3 = Ogre::Vector3(postHavokVelocity.getQuad().v[0], postHavokVelocity.getQuad().v[1], postHavokVelocity.getQuad().v[2]);
  689. Ogre::Vector3 postHavokAngularVelocityV3 = Ogre::Vector3(postHavokAngularVelocity.getQuad().v[0], postHavokAngularVelocity.getQuad().v[1], postHavokAngularVelocity.getQuad().v[2]);
  690. Ogre::Quaternion postHavokOrientationQ = Ogre::Quaternion(postHavokOrientation.m_vec.getQuad().v[3], postHavokOrientation.m_vec.getQuad().v[0], postHavokOrientation.m_vec.getQuad().v[1], postHavokOrientation.m_vec.getQuad().v[2]);
  691. // If this is the server, it is the authority on objects' spatial properties. Thus, we have to:
  692. // 1. Update the "real" (server-side) positions with the new values obtained from the havok objects' rigid bodies
  693. // 2. Update the current positions with the new values
  694. // 3. If this object is owned by the server, then we automatically flag it as server-corrected
  695. // Otherwise, we only flag the object as server-corrected if the new spatial information is outside a certain bounds
  696. if(topology == SERVER)
  697. {
  698. realPosition = postHavokPositionV3;
  699. realVelocity = postHavokVelocityV3;
  700. realAngularVelocity = postHavokAngularVelocityV3;
  701. realOrientation = postHavokOrientationQ;
  702. // If this object is owned by us (the server), then we set the "client" values and mark it as server-corrected.
  703. if(isOwner)
  704. {
  705. position = postHavokPositionV3;
  706. velocity = postHavokVelocityV3;
  707. angularVelocity = postHavokAngularVelocityV3;
  708. orientation = postHavokOrientationQ;
  709. serverCorrected = true;
  710. }
  711. else
  712. {
  713. // Otherwise, this object is "owned" by a client and we only want to send an update if the new
  714. // spatial information is out of a certain bounds. If it is, correct the "client" information and mark it
  715. // as server-corrected.
  716. if(HavokObjectUpdateTest(position, postHavokPositionV3, velocity, postHavokVelocityV3, angularVelocity, postHavokAngularVelocityV3,
  717. orientation, postHavokOrientationQ, Ogre::Real(1), Ogre::Radian(Ogre::Degree(1))))
  718. {
  719. position = postHavokPositionV3;
  720. velocity = postHavokVelocityV3;
  721. angularVelocity = postHavokAngularVelocityV3;
  722. orientation = postHavokOrientationQ;
  723. serverCorrected = true;
  724. }
  725. }
  726. }
  727. else
  728. {
  729. // This is the client, where we are the authority on only the objects we create on the client.
  730. // 1. Store the old, pre-Havok-step information
  731. // 2. If the object is flagged to use server physics only, we reverse the Havok update by restoring the old values
  732. // 3. If the object is not a keyframed object, then update the current (client-side) information with the Havok update
  733. // Otherwise (for keyframed objects), we set the "real" spatial information to match the previous update
  734. // This is a fix that prevents keyframed objects from spazzing out because of the local Havok step
  735. // This *should* be ok, because the server maintains these objects' motion anyway
  736. // 4. Mark only the replicas that have moved substantially as client-modified
  737. // Reset values to the last server update if this object is flagged to use the server's physics only.
  738. // Also, do this for keyframed objects, as the server will determine its position and orientation information
  739. Ogre::Vector3 oldClientPosition = position;
  740. Ogre::Quaternion oldClientOrientation = orientation;
  741. Ogre::Vector3 oldClientVelocity = velocity;
  742. Ogre::Vector3 oldClientAngularVelocity = angularVelocity;
  743. if(useServerPhysicsOnly || m_eGameObjectType == PHYSICS_KEYFRAMED)
  744. {
  745. clientModified = false;
  746. position = realPosition;
  747. orientation = realOrientation;
  748. velocity = realVelocity;
  749. angularVelocity = realAngularVelocity;
  750. //raknet 4.0b8
  751. //realPosition = postHavokPositionV3;
  752. SetHavokRigidBodyInfo(realPosition, realOrientation, realVelocity, realAngularVelocity);
  753. return;
  754. }
  755. // Set the client-side information with the post-Havok-step values...
  756. position = postHavokPositionV3;
  757. velocity = postHavokVelocityV3;
  758. angularVelocity = postHavokAngularVelocityV3;
  759. orientation = postHavokOrientationQ;
  760. // Flag the object as client-modified if there was a change beyond a certain spatial bounds.
  761. if(HavokObjectUpdateTest(postHavokPositionV3, oldClientPosition, postHavokVelocityV3, oldClientVelocity,
  762. postHavokAngularVelocityV3, oldClientAngularVelocity, postHavokOrientationQ, oldClientOrientation,
  763. Ogre::Real(1), Ogre::Radian(Ogre::Degree(1))))
  764. {
  765. clientModified = true;
  766. }
  767. }
  768. }*/
  769. /// SetSceneManager - Sets a pointer to the Ogre scene manager the Havok object is being rendered in.
  770. void GameObjectReplica::SetSceneManager(Ogre::SceneManager *newSceneManager) { sceneManager = newSceneManager; }
  771. /// SetGameObjectManager - Sets a pointer to the Havok GameObjectManager the Havok object will be stored in.
  772. void GameObjectReplica::SetGameObjectManager(GameObjectManager *newManager) { owningManager = newManager; }
  773. /// SetUseServerPhysicsOnly - Sets a flag indicating whether the local physics updates for an object should be ignored.
  774. void GameObjectReplica::SetUseServerPhysicsOnly(bool newUSPO) { useServerPhysicsOnly = newUSPO; }
  775. /// GetSceneManager - Gets a pointer to the Ogre scene manager the Havok object is rendered in. Can be NULL.
  776. Ogre::SceneManager * GameObjectReplica::GetSceneManager() { return sceneManager; }
  777. /// GetGameObjectManager - Gets a pointer to the GameObjectManager the Havok object is stored in. Can be NULL.
  778. GameObjectManager * GameObjectReplica::GetGameObjectManager() { return owningManager; }
  779. /// GetSceneManager - Gets a flag indicating whether the object should use only physics updates from the server.
  780. bool GameObjectReplica::GetUseServerPhysicsOnly() { return useServerPhysicsOnly; }
  781. } // end namespace GamePipeGame
  782. #endif