/Core/Dependencies/Engine/MultiplayerOnline/RakNet/PhysXGameObjectReplica.cpp
C++ | 923 lines | 375 code | 113 blank | 435 comment | 49 complexity | 556693624b538a93c66a31bfa13c4842 MD5 | raw file
- #include "StdAfx.h"
- #ifdef PHYSX
- #include "PhysXGameObjectReplica.h"
- #include <string>
- #include <iostream>
- //#include "HavokNetManager.h"
- using namespace std;
- namespace GamePipeGame
- {
- ofstream outputLog;
-
- /// GameObjectReplica - Constructor
- GameObjectReplica::GameObjectReplica()
- : BasicReplica(),
- havokGameObject(NULL),
- m_sHKXFileName(""),
- m_eGameObjectType(0),
- angularVelocity(Ogre::Vector3::ZERO), realAngularVelocity(Ogre::Vector3::ZERO),
- sceneManager(NULL), owningManager(NULL),
- useServerPhysicsOnly(false),
- currentAnimation("None")
- {
- }
- /// GameObjectReplica - Constructor
- ///
- /// Parameters:
- /// newName - a name for this object. Does not have to be unique.
- /// newMesh - the filename of the mesh for this object. Default value is empty.
- /// newEntity - an entity name for this object, which would likely be determined later anyway. Default value is empty.
- /// newMass - a value for an object's weight. Default value is zero.
- GameObjectReplica::GameObjectReplica(Ogre::String newName, Ogre::String newMesh, Ogre::String newEntity, Ogre::Real newMass)
- : BasicReplica(newName, newMesh, newEntity, newMass),
- havokGameObject(NULL),
- m_sHKXFileName(""),
- m_eGameObjectType(0),
- angularVelocity(Ogre::Vector3::ZERO), realAngularVelocity(Ogre::Vector3::ZERO),
- sceneManager(NULL), owningManager(NULL),
- useServerPhysicsOnly(false),
- currentAnimation("None")
- {
- }
- /// ~GameObjectReplica - Destructor
- ///
- /// This function also cleans up associated Havok objects and further associated Ogre objects created by said Havok objects.
- GameObjectReplica::~GameObjectReplica()
- {
- // We have to do a little cleanup first before this replica can be destroyed
- // properly (because the Havok object doesn't pick up after itself...)
- //
- // 1. Remove the reference to the havok object from the havok world
- // 2. Remove the havok object from the GameObjectManager's list
- // 3. Remove the Ogre entity and its parent scene node from the scene.
- if(havokGameObject != NULL && owningManager != NULL)
- {
- owningManager->RemoveGameObject(havokGameObject);
- }
- else
- cout << "[GameObjectReplica/destructor] Could not remove havok information, as there was no valid GameObject or GameObjectManager pointer." << endl;
- if(sceneManager != NULL)
- {
- Ogre::Entity *entity = sceneManager->getEntity(entityName);
- if(entity != NULL)
- {
- Ogre::SceneNode *sceneNode = entity->getParentSceneNode();
- if(sceneNode != NULL) sceneManager->destroySceneNode(sceneNode);
- sceneManager->destroyEntity(entity);
- }
- else
- {
- cout << "[GameObjectReplica/destructor] Could not destroy Ogre scene information, as " << entityName << " could not be found." << endl;
- }
- }
- }
- /// GetName - Returns a print out of a name, suitable for framing. Virtual, redefined from GameObjectReplica.
- RakNet::RakString
- GameObjectReplica::GetName() const
- {
- Ogre::String ogreString = "Class: GameObjectReplica, Name: ";
- ogreString += objName;
- return RakNet::RakString(ogreString.c_str());
- }
- /// WriteAllocationID - Writes a unique string to be used by the replica factory. Virtual, redefined from GameObjectReplica.
- ///
- /// Parameters:
- /// allocationIdBitstream - a RakNet BitStream where the allocation string will be written to (and later read from by the factory)
- void
- GameObjectReplica::WriteAllocationID(RakNet::Connection_RM3 *destinationConnection, RakNet::BitStream *allocationIdBitstream) const
- {
- Ogre::String className = "GameObjectReplica";
- allocationIdBitstream->Write(className.c_str());
- }
- /// SerializeConstruction - Serializes data for a remote object reference/creation call.
- /// Virtual, redefined from GameObjectReplica.
- ///
- /// Parameters:
- /// constructionBitstream - a RakNet BitStream containing the data to be used in the object's remote construction
- /// destinationConnection - the connection the remote object will be created on (in case special serialization is needed)
- void
- GameObjectReplica::SerializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *destinationConnection)
- {
- constructionBitstream->Write(GetName() + RakNet::RakString(" SerializeConstruction"));
- constructionBitstream->Write(RakNet::RakString(objName.c_str()));
- constructionBitstream->Write(RakNet::RakString(meshName.c_str()));
- constructionBitstream->Write(RakNet::RakString(m_sHKXFileName.c_str()));
- constructionBitstream->Write(mass);
- constructionBitstream->Write((int)m_eGameObjectType);
- constructionBitstream->Write(position.x);
- constructionBitstream->Write(position.y);
- constructionBitstream->Write(position.z);
- constructionBitstream->Write(orientation.x);
- constructionBitstream->Write(orientation.y);
- constructionBitstream->Write(orientation.z);
- constructionBitstream->Write(orientation.w);
- constructionBitstream->Write(velocity.x);
- constructionBitstream->Write(velocity.y);
- constructionBitstream->Write(velocity.z);
- constructionBitstream->Write(angularVelocity.x);
- constructionBitstream->Write(angularVelocity.y);
- constructionBitstream->Write(angularVelocity.z);
- //@Animation
- constructionBitstream->Write(RakNet::RakString(currentAnimation.c_str()));
- if(topology == SERVER)
- {
- entityName = objName;
- entityName.append(".");
- //entityName.append(Ogre::StringConverter::toString((int)GetNetworkID().localSystemAddress));
- // raknet 4.0b8
- entityName.append(Ogre::StringConverter::toString((int)GetNetworkID()));
- }
- else
- {
- }
- }
- /// DeserializeConstruction - Reads and processes incoming data from a remote object reference/creation call.
- /// Virtual, redefined from GameObjectReplica.
- ///
- /// Parameters:
- /// constructionBitstream - a RakNet BitStream containing the data to be used in the object's remote construction
- /// sourceConnection - the connection calling for the construction of the object represented by this replica
- bool
- GameObjectReplica::DeserializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *sourceConnection)
- {
- RakNet::RakString rakString;
- RakNet::RakString rakStringObjectName;
- RakNet::RakString rakStringMeshName;
- RakNet::RakString rakStringHavokObjectFileName;
- RakNet::RakString rakStringHavokObjectModelName;
- Ogre::Real initialMass;
- int initialHavokObjectType; //initialHavokObjectSubType;
- Ogre::Vector3 initialPosition, initialVelocity, initialAngularVelocity;
- Ogre::Quaternion initialOrientation;
- constructionBitstream->Read(rakString);
- constructionBitstream->Read(rakStringObjectName);
- constructionBitstream->Read(rakStringMeshName);
- constructionBitstream->Read(rakStringHavokObjectFileName);
- //constructionBitstream->Read(rakStringHavokObjectModelName);
- constructionBitstream->Read(initialMass);
- constructionBitstream->Read(initialHavokObjectType);
- //constructionBitstream->Read(initialHavokObjectSubType);
- constructionBitstream->Read(initialPosition.x);
- constructionBitstream->Read(initialPosition.y);
- constructionBitstream->Read(initialPosition.z);
- constructionBitstream->Read(initialOrientation.x);
- constructionBitstream->Read(initialOrientation.y);
- constructionBitstream->Read(initialOrientation.z);
- constructionBitstream->Read(initialOrientation.w);
- constructionBitstream->Read(initialVelocity.x);
- constructionBitstream->Read(initialVelocity.y);
- constructionBitstream->Read(initialVelocity.z);
- constructionBitstream->Read(initialAngularVelocity.x);
- constructionBitstream->Read(initialAngularVelocity.y);
- constructionBitstream->Read(initialAngularVelocity.z);
- //@Animation
- RakNet::RakString rakAnimationString;
- constructionBitstream->Read(rakAnimationString);
- currentAnimation = rakAnimationString.C_String();
- objName = rakStringObjectName.C_String();
- meshName = rakStringMeshName.C_String();
- m_sHKXFileName = rakStringHavokObjectFileName.C_String();
- mass = initialMass;
- m_eGameObjectType = initialHavokObjectType;
- position = realPosition = initialPosition;
- orientation = realOrientation = initialOrientation;
- velocity = realVelocity = initialVelocity;
- angularVelocity = realAngularVelocity = initialAngularVelocity;
- if(topology == CLIENT)
- {
- entityName = objName;
- entityName.append(".");
- //entityName.append(Ogre::StringConverter::toString((int)GetNetworkID().localSystemAddress));
- //raknet 4.0b8
- entityName.append(Ogre::StringConverter::toString((int)GetNetworkID()));
- }
- else
- {
- }
- return true;
- }
- /// DeallocReplica - Determines what should be done when a replica should be deleted. Virtual, redefined from GameObjectReplica.
- ///
- /// Parameters:
- /// sourceConnection - the connection calling for the destruction of the object represented by this replica
- void
- GameObjectReplica::DeallocReplica(RakNet::Connection_RM3 *sourceConnection)
- {
- // RMF deleting the object here consistently causes a crash having to do with m_pGraphicsObject.
- //delete this;
- }
- /// Serialize - Writes data to a Bitstream to be sent to a remote system. Virtual, redefined from GameObjectReplica.
- ///
- /// If allowed to by the returned result of QuerySerialize, this function runs every call to replicaManager->Update(),
- /// for every object, for every connection.
- ///
- /// Parameters:
- /// serializeParameters - a RakNet SerializeParameters class containing the serialized information to be sent
- RakNet::RM3SerializationResult
- GameObjectReplica::Serialize(RakNet::SerializeParameters *serializeParameters)
- {
- // If we are a client:
- // 1. If this replica is flagged to use server physics, we don't serialize this (might need to move this to QuerySerialize)
- // 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
- // Otherwise, reset the client-modified flag and serialize normally
- if(topology1 == CLIENT)
- {
- if(useServerPhysicsOnly) return RakNet::RM3SR_DO_NOT_SERIALIZE;
- /*RakNetTime diffUpdateTime = RakNet::GetTime() - lastUpdateClient;*/
- //raknet 4.0b8
- RakNet::Time diffUpdateTime = RakNet::GetTime() - lastUpdateClient;
- if(!clientModified && ( (RakNet::GetTime() - lastUpdateClient) < 1000) )
- {
- // cout << "[GameObjectReplica/Serialize] CLIENT: no local modification, should skip serialization this tick" << endl;
- return RakNet::RM3SR_DO_NOT_SERIALIZE;
- }
- else
- {
- // cout << "[GameObjectReplica/Serialize] CLIENT: locally modified, should serialize to server and reset modification flag" << endl;
- clientModified = false;
- }
- }
- /*RakNetTime time = RakNet::GetTime()/1000;*/
- //raknet 4.0b8
- RakNet::Time time = RakNet::GetTime()/1000;
- serializeParameters->outputBitstream[0].Write(time);
- serializeParameters->outputBitstream[0].Write(position.x);
- serializeParameters->outputBitstream[0].Write(position.y);
- serializeParameters->outputBitstream[0].Write(position.z);
- serializeParameters->outputBitstream[0].Write(realPosition.x);
- serializeParameters->outputBitstream[0].Write(realPosition.y);
- serializeParameters->outputBitstream[0].Write(realPosition.z);
- serializeParameters->outputBitstream[0].Write(orientation.x);
- serializeParameters->outputBitstream[0].Write(orientation.y);
- serializeParameters->outputBitstream[0].Write(orientation.z);
- serializeParameters->outputBitstream[0].Write(orientation.w);
- serializeParameters->outputBitstream[0].Write(realOrientation.x);
- serializeParameters->outputBitstream[0].Write(realOrientation.y);
- serializeParameters->outputBitstream[0].Write(realOrientation.z);
- serializeParameters->outputBitstream[0].Write(realOrientation.w);
- serializeParameters->outputBitstream[0].Write(velocity.x);
- serializeParameters->outputBitstream[0].Write(velocity.y);
- serializeParameters->outputBitstream[0].Write(velocity.z);
- serializeParameters->outputBitstream[0].Write(realVelocity.x);
- serializeParameters->outputBitstream[0].Write(realVelocity.y);
- serializeParameters->outputBitstream[0].Write(realVelocity.z);
- serializeParameters->outputBitstream[0].Write(angularVelocity.x);
- serializeParameters->outputBitstream[0].Write(angularVelocity.y);
- serializeParameters->outputBitstream[0].Write(angularVelocity.z);
- serializeParameters->outputBitstream[0].Write(realAngularVelocity.x);
- serializeParameters->outputBitstream[0].Write(realAngularVelocity.y);
- serializeParameters->outputBitstream[0].Write(realAngularVelocity.z);
- //@Animation
- //Note entering here since no string entered here
- serializeParameters->outputBitstream[0].Write(RakNet::RakString(currentAnimation.c_str()));
- // set a non-zero value so the timestamp is passed
- serializeParameters->messageTimestamp = RakNet::GetTime();
- // update the appropriate timestamp for the source of this update (can be used later for interpolation)
- if(topology == CLIENT)
- lastUpdateClient = RakNet::GetTime();
- else
- lastUpdateServer = RakNet::GetTime();
- return RakNet::RM3SR_BROADCAST_IDENTICALLY;
- }
- /// Deserialize - Reads and processes incoming data from a remote serialization.
- /// Virtual, redefined from GameObjectReplica.
- ///
- /// Parameters:
- /// deserializeParameters - a RakNet DeserializeParameters class containing the serialized information to be read
- void
- GameObjectReplica::Deserialize(RakNet::DeserializeParameters *deserializeParameters)
- {
- //RakNetTime dsTime;
- //raknet 4.0b8
- RakNet::Time dsTime;
- Ogre::Vector3 newPosition, newRealPosition;
- Ogre::Quaternion newOrientation, newRealOrientation;
- Ogre::Vector3 newVelocity, newRealVelocity;
- Ogre::Vector3 newAngularVelocity, newRealAngularVelocity;
- // Read in the values from the serialization string here. The order has to match the original serialization order.
- deserializeParameters->serializationBitstream[0].Read(dsTime);
- deserializeParameters->serializationBitstream[0].Read(newPosition.x);
- deserializeParameters->serializationBitstream[0].Read(newPosition.y);
- deserializeParameters->serializationBitstream[0].Read(newPosition.z);
- deserializeParameters->serializationBitstream[0].Read(newRealPosition.x);
- deserializeParameters->serializationBitstream[0].Read(newRealPosition.y);
- deserializeParameters->serializationBitstream[0].Read(newRealPosition.z);
- deserializeParameters->serializationBitstream[0].Read(newOrientation.x);
- deserializeParameters->serializationBitstream[0].Read(newOrientation.y);
- deserializeParameters->serializationBitstream[0].Read(newOrientation.z);
- deserializeParameters->serializationBitstream[0].Read(newOrientation.w);
- deserializeParameters->serializationBitstream[0].Read(newRealOrientation.x);
- deserializeParameters->serializationBitstream[0].Read(newRealOrientation.y);
- deserializeParameters->serializationBitstream[0].Read(newRealOrientation.z);
- deserializeParameters->serializationBitstream[0].Read(newRealOrientation.w);
- deserializeParameters->serializationBitstream[0].Read(newVelocity.x);
- deserializeParameters->serializationBitstream[0].Read(newVelocity.y);
- deserializeParameters->serializationBitstream[0].Read(newVelocity.z);
- deserializeParameters->serializationBitstream[0].Read(newRealVelocity.x);
- deserializeParameters->serializationBitstream[0].Read(newRealVelocity.y);
- deserializeParameters->serializationBitstream[0].Read(newRealVelocity.z);
- deserializeParameters->serializationBitstream[0].Read(newAngularVelocity.x);
- deserializeParameters->serializationBitstream[0].Read(newAngularVelocity.y);
- deserializeParameters->serializationBitstream[0].Read(newAngularVelocity.z);
- deserializeParameters->serializationBitstream[0].Read(newRealAngularVelocity.x);
- deserializeParameters->serializationBitstream[0].Read(newRealAngularVelocity.y);
- deserializeParameters->serializationBitstream[0].Read(newRealAngularVelocity.z);
- //@Animation
- RakNet::RakString rakAnimationString;
- deserializeParameters->serializationBitstream[0].Read(rakAnimationString);
- currentAnimation = rakAnimationString.C_String();
- // Now that we have all of the serialized values from the update, we have to determine what to do with them.
- // If we are the server:
- // 1. Set the last client update time (this can be used later for extrapolation)
- // 2. Check the values for validity. There's no real checking done below, and so we accept the values as valid by default
- // If the value(s) are valid:
- // 1. Set the "local" and the server-side values to the client-requested values
- // 2. Update the rigid body information with this new update so it can be processed by the Havok world later
- if(topology == SERVER)
- {
- lastUpdateClient = RakNet::GetTime();
- if(true) // sanity check the position update sent from the client
- {
- position = realPosition = newPosition;
- orientation = realOrientation = newOrientation;
- velocity = realVelocity = newVelocity;
- angularVelocity = realAngularVelocity = newAngularVelocity;
- //if(havokGameObject != NULL) SetHavokRigidBodyInfo(position, orientation, velocity, angularVelocity);
- }
- else
- serverCorrected = true;
- }
- else
- {
- // Otherwise, this is a client:
- // 1. Set the last server update time (this can be used later for extrapolation)
- // 2. If the update from the server is different than the last update (the values currently stored in the real* variables):
- // If this object is a keyframed object, we only copy the position and orientation values.
- // Otherwise, this is a normal object and:
- // 1. Update the server values with the latest values from the server
- // 2. Update the client-side positions only if the server update is outside of a specific range, or we don't own this object
- lastUpdateServer = RakNet::GetTime();
- if(realPosition != newRealPosition || realOrientation != newRealOrientation || velocity != newRealVelocity || angularVelocity != newAngularVelocity)
- {
- if(m_eGameObjectType == PHYSICS_KEYFRAMED)
- {
- position = realPosition = newPosition;
- orientation = realOrientation = newOrientation;
- velocity = realVelocity = Ogre::Vector3::ZERO;
- angularVelocity = realAngularVelocity = Ogre::Vector3::ZERO;
- }
- else
- {
- realPosition = newRealPosition;
- realOrientation = newRealOrientation;
- realVelocity = newRealVelocity;
- realAngularVelocity = newRealAngularVelocity;
- if(position.squaredDistance(realPosition) > 1 || !orientation.equals(realOrientation, Ogre::Radian((Ogre::Real)0.1475)) ||
- //creatingSystemGUID != replicaManager->GetRakPeerInterface()->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS))
- //raknet 4.0b8
- creatingSystemGUID != replicaManager->GetRakPeerInterface()->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS))
- {
- // This section would probably be better done by using lerp for position and slerp for orientation instead of direct copy
- position = realPosition;
- orientation = realOrientation;
- velocity = realVelocity;
- angularVelocity = realAngularVelocity;
- }
- }
- // update the rigid body information with the correctly updated information
- //if(havokGameObject != NULL) SetHavokRigidBodyInfo(position, orientation, velocity, angularVelocity);
- // flag to indicate this was corrected by the server, might be vestigial now
- serverCorrected = true;
- }
- }
- }
- /* Havok-related functions */
- /// GetHavokGameObject - Sets a pointer to the Havok GameObject associated with this replica
- /*void GameObjectReplica::SetHavokGameObject(GameObject *newHavokGameObject) {havokGameObject = newHavokGameObject; }
- /// GetHavokObjectFileName - Sets the filename where the object's Havok information is stored (eg., "object.hkx")
- void GameObjectReplica::SetHavokObjectFileName(const char *newHavokObjectFileName) { m_sHKXFileName = newHavokObjectFileName; }
- void
- GameObjectReplica::SetHavokObjectFileInfo(const char *newHavokObjectFileName, const char *newMeshName)
- {
- SetHavokObjectFileName(newHavokObjectFileName);
- SetMeshName(newMeshName);
- }
- /// SetHavokObjectType - Sets an object's primary Havok type (GameObjectType)
- void GameObjectReplica::SetHavokObjectType(int newHavokObjectType) { m_eGameObjectType = newHavokObjectType; }*/
- /// SetAngularVelocity - Sets the local value for an object's angular velocity. Uses 3 floats.
- void GameObjectReplica::SetAngularVelocity(float x, float y, float z) { angularVelocity = Ogre::Vector3(x, y, z); }
- /// SetAngularVelocity - Sets the local value for an object's angular velocity. Uses a Vector3.
- void GameObjectReplica::SetAngularVelocity(Ogre::Vector3 newAngularVelocity) { angularVelocity = newAngularVelocity; }
- /// SetRealAngularVelocity - Sets the server's last updated value for an object's angular velocity. Uses 3 floats.
- void GameObjectReplica::SetRealAngularVelocity(float x, float y, float z) { realAngularVelocity = Ogre::Vector3(x, y, z); }
- /// SetRealAngularVelocity - Sets the server's last updated value for an object's angular velocity. Uses a Vector3.
- void GameObjectReplica::SetRealAngularVelocity(Ogre::Vector3 newRealAngularVelocity) { realAngularVelocity = newRealAngularVelocity; }
- /// GetHavokGameObject - Gets a pointer to the Havok GameObject associated with this replica
- /*GameObject * GameObjectReplica::GetHavokGameObject() { return havokGameObject; }
- /// GetHavokObjectFileName - Gets the filename where the object's Havok information is stored (eg., "object.hkx")
- Ogre::String GameObjectReplica::GetHavokObjectFileName() { return m_sHKXFileName; }
- /// GetHavokObjectType - Gets an object's primary Havok type (GameObjectType)
- GameObjectType GameObjectReplica::GetHavokObjectType() { return static_cast<GameObjectType>(m_eGameObjectType); }*/
- /// GetAngularVelocity - Gets the local value for an object's angular velocity.
- Ogre::Vector3 GameObjectReplica::GetAngularVelocity() { return angularVelocity; }
- /// GetRealAngularVelocity - Gets the server's last updated value for an object's angular velocity.
- Ogre::Vector3 GameObjectReplica::GetRealAngularVelocity() { return realAngularVelocity; }
- /// GetHavokRigidBodyInfo - Copies spatial and physics information from a Havok GameObject
- ///
- /// This function accounts for the different Havok object types.
- ///
- /// Parameters:
- /// hkPosition - a reference to a Havok position vector
- /// hkVelocity - a reference to a Havok velocity vector
- /// hkAngularVelocity - a reference to a Havok angular velocity vector
- /// hkOrientation - a reference to a Havok orientation quaternion
- /*void
- GameObjectReplica::GetHavokRigidBodyInfo(hkVector4 &hkPosition, hkVector4 &hkVelocity, hkVector4 &hkAngularVelocity, hkQuaternion &hkOrientation)
- {
- hkPosition.set(0, 0, 0);
- hkVelocity.set(0, 0, 0);
- hkAngularVelocity.set(0, 0, 0);
- hkOrientation.m_vec.set(0, 0, 0, 1);
- // The raw spatial information is available through different sources depending on the Havok object type
- // Here we have to differentiate between the following Havok types:
- // 1. {CHARACTER, CHARACTER_RIGIDBODY) - information is available through the CharacterRigidBodyObject->hkpRigidBody pointer
- // 2. {CHARACTER, CHARACTER_PROXY} - only position and velocity information is available, orientation/angular velocity not supported
- // 3. {PHYSICS, *} - information is available through the PhysicsObject->hkpRigidBody pointer
- if ((havokGameObject->m_eObjectType == ANIMATED_CHARACTER_RIGIDBODY)||(havokGameObject->m_eObjectType == PHYSICS_CHARACTER_RIGIDBODY))
- {
- CharacterRigidBodyObject *crbo = static_cast<CharacterRigidBodyObject *>(havokGameObject->m_pPhysicsObject);
- hkPosition = crbo->getCharacterRigidBody()->getRigidBody()->getPosition();
- hkVelocity = crbo->getCharacterRigidBody()->getRigidBody()->getLinearVelocity();
- hkAngularVelocity = crbo->getCharacterRigidBody()->getRigidBody()->getAngularVelocity();
- hkOrientation = crbo->getCharacterRigidBody()->getRigidBody()->getRotation();
- }
- else if((havokGameObject->m_eObjectType == ANIMATED_CHARACTER_PROXY)||(havokGameObject->m_eObjectType == PHYSICS_CHARACTER_PROXY))
- {
- CharacterProxyObject *cpo = static_cast<CharacterProxyObject *>(havokGameObject->m_pPhysicsObject);
- hkPosition = cpo->getCharacterProxy()->getPosition();
- hkVelocity = cpo->getCharacterProxy()->getLinearVelocity();
- }
- else
- {
- Ogre::Vector3 gameObjectPosition = havokGameObject->getPosition();
- hkPosition = hkVector4(gameObjectPosition.x,gameObjectPosition.y,gameObjectPosition.z);
- PhysicsPrimitiveObject* f_pTempObject = (PhysicsPrimitiveObject*)havokGameObject->m_pPhysicsObject;
- if (f_pTempObject!=NULL)
- {
- hkOrientation = f_pTempObject->getRigidBody()->getRotation();
- hkVelocity = f_pTempObject->getRigidBody()->getLinearVelocity();
- hkAngularVelocity = f_pTempObject->getRigidBody()->getAngularVelocity();
- }
- else//this should be fixed, functions should be added to PhysicsObject and all children under it
- { hkOrientation = hkQuaternion(0,0,0,1);
- hkVelocity = hkVector4(0,0,0);
- hkAngularVelocity = hkVector4(0,0,0);
- }
- }
- }
- /// SetHavokRigidBodyInfo - Copies spatial and physics information into a Havok GameObject
- ///
- /// This function converts Ogre data types to Havok data types and accounts for the different Havok object types.
- ///
- /// Parameters:
- /// updatePosition - a new position vector
- /// updateOrientation - a new orientation quaternion
- /// updateVelocity - a new velocity vector
- /// updateAngularVelocity - a new angular velocity vector
- void
- GameObjectReplica::SetHavokRigidBodyInfo(Ogre::Vector3 updatePosition, Ogre::Quaternion updateOrientation, Ogre::Vector3 updateVelocity, Ogre::Vector3 updateAngularVelocity)
- {
- hkVector4 newPosition, newVelocity, newAngularVelocity;
- hkQuaternion newOrientation;
- newPosition.set(updatePosition.x, updatePosition.y, updatePosition.z);
- newVelocity.set(updateVelocity.x, updateVelocity.y, updateVelocity.z);
- newAngularVelocity.set(updateAngularVelocity.x, updateAngularVelocity.y, updateAngularVelocity.z);
- newOrientation.m_vec.set(updateOrientation.x, updateOrientation.y, updateOrientation.z, updateOrientation.w);
- if((havokGameObject->m_eObjectType == ANIMATED_CHARACTER_RIGIDBODY)||(havokGameObject->m_eObjectType == PHYSICS_CHARACTER_RIGIDBODY))
- {
- CharacterRigidBodyObject *crbo = dynamic_cast<CharacterRigidBodyObject *>(havokGameObject->m_pPhysicsObject);
- crbo->getCharacterRigidBody()->getRigidBody()->setPosition(newPosition);
- crbo->getCharacterRigidBody()->getRigidBody()->setRotation(newOrientation);
- crbo->getCharacterRigidBody()->getRigidBody()->setLinearVelocity(newVelocity);
- crbo->getCharacterRigidBody()->getRigidBody()->setAngularVelocity(newAngularVelocity);
- }
- else if((havokGameObject->m_eObjectType == ANIMATED_CHARACTER_PROXY)||(havokGameObject->m_eObjectType == PHYSICS_CHARACTER_PROXY))
- {
- CharacterProxyObject *cpo = static_cast<CharacterProxyObject *>(havokGameObject->m_pPhysicsObject);
- cpo->getCharacterProxy()->setPosition(newPosition);
- cpo->getCharacterProxy()->setLinearVelocity(newVelocity);
- }
- else
- {
- havokGameObject->setPosition(updatePosition.x,updatePosition.y,updatePosition.z);
- PhysicsPrimitiveObject* f_pTempObject = (PhysicsPrimitiveObject*)havokGameObject->m_pPhysicsObject;
- if (f_pTempObject!=NULL)
- {
- f_pTempObject->getRigidBody()->setRotation(newOrientation);
- f_pTempObject->getRigidBody()->setLinearVelocity(newVelocity);
- f_pTempObject->getRigidBody()->setAngularVelocity(newAngularVelocity);
- }
- else
- {
- //do we need to set these parameters unless the object is physics primitive??
- //this should be fixed, functions should be added to PhysicsObject and all children under it
- }
- }
- }*/
- /// playAnimation - Play animation on GameObject for this replica
- /// Parameters: animationName - Name of animation to be played
- ///
- /// Returns: Nothing.
- void GameObjectReplica::playAnimation(Ogre::String animationName)
- {
- if(havokGameObject==NULL)
- {
- //try finding
- Ogre::String objectName = GetObjectName();
- Ogre::String newEntityName = objectName + ".";
- newEntityName.append(Ogre::StringConverter::toString((int)(GetNetworkID())));
- GameObject *hgameobject = GetGameObjectManager()->GetGameObject(newEntityName);
- if(hgameobject==NULL)
- return;
- else
- havokGameObject = hgameobject;
- }
- if(hasAnimation(animationName))
- {
- havokGameObject->m_pAnimatedEntity->StopAnimation();
- havokGameObject->PlayAnimation(animationName);
- currentAnimation = animationName;
- return;
- }
- else
- {
- currentAnimation="None";
- stopAnimation();
- }
- }
- /// stopAnimation - Stop animation on GameObject for this replica. If no name is specified, stops all animations
- /// Parameters: animationName - Name of animation to be stopeed
- ///
- /// Returns: Nothing.
- void GameObjectReplica::stopAnimation(Ogre::String animationName)
- {
- if(havokGameObject==NULL)
- {
- //try finding
- Ogre::String objectName = GetObjectName();
- Ogre::String newEntityName = objectName + ".";
- newEntityName.append(Ogre::StringConverter::toString((int)(GetNetworkID())));
- GameObject *hgameobject = GetGameObjectManager()->GetGameObject(newEntityName);
- if(hgameobject==NULL)
- return;
- else
- havokGameObject = hgameobject;
- }
- if(animationName=="")
- {
- currentAnimation="None";
- havokGameObject->m_pAnimatedEntity->StopAnimation();
- }
- else if(currentAnimation==animationName)
- {
- currentAnimation="None";
- havokGameObject->m_pAnimatedEntity->StopAnimation();
- }
- else
- return;
-
- }
- /// hasAnimation - Returns whether or not replica has an animation or not
- /// Parameters: animationName - Name of animation to be queried
- ///
- /// Returns: bool depending on animation found or not
- bool GameObjectReplica::hasAnimation(Ogre::String animationName)
- {
- if(havokGameObject==NULL)
- {
- //try finding
- Ogre::String objectName = GetObjectName();
- Ogre::String newEntityName = objectName + ".";
- newEntityName.append(Ogre::StringConverter::toString((int)(GetNetworkID())));
- GameObject *hgameobject = GetGameObjectManager()->GetGameObject(newEntityName);
- if(hgameobject==NULL)
- return false;
- else
- havokGameObject = hgameobject;
- }
- if(havokGameObject->HasAnimationName(animationName))
- return true;
- return false;
- }
- /// ProcessHavokStep - Processes an object after a previous Havok world simulation step.
- ///
- /// Using this information, a server can determine whether it should send out an update for an object it's responsible for.
- /// A client will be able to use this function to determine whether it should send its own update, or rollback changes made
- /// by its local physics world.
- ///
- /// Parameters: isOwner - a flag indicating whether the GUID of the system creating the replica matches the GUID of this system
- ///
- /// Returns: Nothing. A call to this function when a Havok GameObject does not exist will simply return.
- /*void
- GameObjectReplica::ProcessHavokStep(bool isOwner,NetTopology topology)
- {
- // If there's no associated Havok GameObject, then there's no point in updating.
- if(havokGameObject == NULL) return;
- AnimationManager::AnimatedEntity *animatedEntity = havokGameObject->m_pAnimatedEntity;
- if(animatedEntity!=NULL)
- {
-
- if(topology == SERVER)
- {
- // isanimationplaying not working with havok animation so cant use server update
- }
- else
- {
- if(currentAnimation=="None")
- {
- animatedEntity->StopAnimation();
- }
- else if(animatedEntity->HasAnimationName(currentAnimation) && currentAnimation!=animatedEntity->GetActiveAnimation())
- {
-
- if((m_sHKXFileName=="" && !animatedEntity->IsAnimationPlaying(currentAnimation.c_str())))
- havokGameObject->PlayAnimation(currentAnimation);
- else if(m_sHKXFileName.length() > 0)
- {
- animatedEntity->StopAnimation();
- havokGameObject->PlayAnimation(currentAnimation);
- }
-
- }
- else if(animatedEntity->HasAnimationName(currentAnimation))
- {
- //do nothing
- }
- else
- {
- animatedEntity->StopAnimation();
- }
- }
- }
- if(havokGameObject->m_eObjectType==GRAPHICS_OBJECT)
- {
- velocity = realVelocity = Ogre::Vector3(0,0,0);
- angularVelocity = realAngularVelocity = Ogre::Vector3(0,0,0);
- if(topology == SERVER)
- {
- position = realPosition = havokGameObject->getPosition();
- serverCorrected = true;
- }
- else
- {
- if(useServerPhysicsOnly)
- {
- position = realPosition;
- havokGameObject->setPosition(realPosition.x,realPosition.y,realPosition.z);
- }
- else
- {
-
- clientModified = true;
- }
- }
- return;
- }
- // Now that the simulation has taken a step, we update the "real" values. If the "real" value is different
- // than the previous value, it has been effectively modified and and it should be serialized to the server/client
- hkVector4 postHavokPosition, postHavokVelocity, postHavokAngularVelocity;
- hkQuaternion postHavokOrientation;
- if(havokGameObject->m_eObjectType!=GRAPHICS_OBJECT)
- GetHavokRigidBodyInfo(postHavokPosition, postHavokVelocity, postHavokAngularVelocity, postHavokOrientation);
- // For readability, I'm converting the Havok types to Ogre types
- Ogre::Vector3 postHavokPositionV3 = Ogre::Vector3(postHavokPosition.getQuad().v[0], postHavokPosition.getQuad().v[1], postHavokPosition.getQuad().v[2]);
- Ogre::Vector3 postHavokVelocityV3 = Ogre::Vector3(postHavokVelocity.getQuad().v[0], postHavokVelocity.getQuad().v[1], postHavokVelocity.getQuad().v[2]);
- Ogre::Vector3 postHavokAngularVelocityV3 = Ogre::Vector3(postHavokAngularVelocity.getQuad().v[0], postHavokAngularVelocity.getQuad().v[1], postHavokAngularVelocity.getQuad().v[2]);
- 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]);
- // If this is the server, it is the authority on objects' spatial properties. Thus, we have to:
- // 1. Update the "real" (server-side) positions with the new values obtained from the havok objects' rigid bodies
- // 2. Update the current positions with the new values
- // 3. If this object is owned by the server, then we automatically flag it as server-corrected
- // Otherwise, we only flag the object as server-corrected if the new spatial information is outside a certain bounds
- if(topology == SERVER)
- {
- realPosition = postHavokPositionV3;
- realVelocity = postHavokVelocityV3;
- realAngularVelocity = postHavokAngularVelocityV3;
- realOrientation = postHavokOrientationQ;
- // If this object is owned by us (the server), then we set the "client" values and mark it as server-corrected.
- if(isOwner)
- {
- position = postHavokPositionV3;
- velocity = postHavokVelocityV3;
- angularVelocity = postHavokAngularVelocityV3;
- orientation = postHavokOrientationQ;
- serverCorrected = true;
- }
- else
- {
- // Otherwise, this object is "owned" by a client and we only want to send an update if the new
- // spatial information is out of a certain bounds. If it is, correct the "client" information and mark it
- // as server-corrected.
- if(HavokObjectUpdateTest(position, postHavokPositionV3, velocity, postHavokVelocityV3, angularVelocity, postHavokAngularVelocityV3,
- orientation, postHavokOrientationQ, Ogre::Real(1), Ogre::Radian(Ogre::Degree(1))))
- {
- position = postHavokPositionV3;
- velocity = postHavokVelocityV3;
- angularVelocity = postHavokAngularVelocityV3;
- orientation = postHavokOrientationQ;
- serverCorrected = true;
- }
- }
- }
- else
- {
- // This is the client, where we are the authority on only the objects we create on the client.
- // 1. Store the old, pre-Havok-step information
- // 2. If the object is flagged to use server physics only, we reverse the Havok update by restoring the old values
- // 3. If the object is not a keyframed object, then update the current (client-side) information with the Havok update
- // Otherwise (for keyframed objects), we set the "real" spatial information to match the previous update
- // This is a fix that prevents keyframed objects from spazzing out because of the local Havok step
- // This *should* be ok, because the server maintains these objects' motion anyway
- // 4. Mark only the replicas that have moved substantially as client-modified
- // Reset values to the last server update if this object is flagged to use the server's physics only.
- // Also, do this for keyframed objects, as the server will determine its position and orientation information
- Ogre::Vector3 oldClientPosition = position;
- Ogre::Quaternion oldClientOrientation = orientation;
- Ogre::Vector3 oldClientVelocity = velocity;
- Ogre::Vector3 oldClientAngularVelocity = angularVelocity;
- if(useServerPhysicsOnly || m_eGameObjectType == PHYSICS_KEYFRAMED)
- {
- clientModified = false;
- position = realPosition;
- orientation = realOrientation;
- velocity = realVelocity;
- angularVelocity = realAngularVelocity;
- //raknet 4.0b8
- //realPosition = postHavokPositionV3;
- SetHavokRigidBodyInfo(realPosition, realOrientation, realVelocity, realAngularVelocity);
- return;
- }
- // Set the client-side information with the post-Havok-step values...
- position = postHavokPositionV3;
- velocity = postHavokVelocityV3;
- angularVelocity = postHavokAngularVelocityV3;
- orientation = postHavokOrientationQ;
- // Flag the object as client-modified if there was a change beyond a certain spatial bounds.
- if(HavokObjectUpdateTest(postHavokPositionV3, oldClientPosition, postHavokVelocityV3, oldClientVelocity,
- postHavokAngularVelocityV3, oldClientAngularVelocity, postHavokOrientationQ, oldClientOrientation,
- Ogre::Real(1), Ogre::Radian(Ogre::Degree(1))))
- {
- clientModified = true;
- }
- }
- }*/
- /// SetSceneManager - Sets a pointer to the Ogre scene manager the Havok object is being rendered in.
- void GameObjectReplica::SetSceneManager(Ogre::SceneManager *newSceneManager) { sceneManager = newSceneManager; }
- /// SetGameObjectManager - Sets a pointer to the Havok GameObjectManager the Havok object will be stored in.
- void GameObjectReplica::SetGameObjectManager(GameObjectManager *newManager) { owningManager = newManager; }
- /// SetUseServerPhysicsOnly - Sets a flag indicating whether the local physics updates for an object should be ignored.
- void GameObjectReplica::SetUseServerPhysicsOnly(bool newUSPO) { useServerPhysicsOnly = newUSPO; }
- /// GetSceneManager - Gets a pointer to the Ogre scene manager the Havok object is rendered in. Can be NULL.
- Ogre::SceneManager * GameObjectReplica::GetSceneManager() { return sceneManager; }
- /// GetGameObjectManager - Gets a pointer to the GameObjectManager the Havok object is stored in. Can be NULL.
- GameObjectManager * GameObjectReplica::GetGameObjectManager() { return owningManager; }
- /// GetSceneManager - Gets a flag indicating whether the object should use only physics updates from the server.
- bool GameObjectReplica::GetUseServerPhysicsOnly() { return useServerPhysicsOnly; }
- } // end namespace GamePipeGame
- #endif