Browse Source

Allow sending client observer rotation in addition to position. Note that rotation is not used by the NetworkPriority component, but can be used for custom logic. Do not send the observer pos/rot until actually set by the client. Closes #428.

Lasse Öörni 11 years ago
parent
commit
0472b4d410

+ 2 - 1
Docs/Reference.dox

@@ -1926,7 +1926,8 @@ A current priority value is calculated on each server update as "base priority -
 
 The default values are base priority 100.0, distance factor 0.0, and minimum priority 0.0. This means that by default an update is always sent (which is also the case if the node has no NetworkPriority component.) Additionally, there is a rule that the node's owner connection always receives updates at full frequency. This rule can be controlled by calling \ref NetworkPriority::SetAlwaysUpdateOwner "SetAlwaysUpdateOwner()".
 
-Calculating the distance requires the client to tell its current observer position (typically, either the camera's or the player character's world position.) This is accomplished by the client code calling \ref Connection::SetPosition "SetPosition()" on the server connection.
+Calculating the distance requires the client to tell its current observer position (typically, either the camera's or the player character's world position.) This is accomplished by the client code calling \ref Connection::SetPosition "SetPosition()" on the server connection. The client can also tell its current observer rotation by
+calling \ref Connection::SetRotation "SetRotation()" but that will only be useful for custom logic, as it is not used by the NetworkPriority component.
 
 For now, creation and removal of nodes is always sent immediately, without consulting interest management. This is based on the assumption that nodes' motion updates consume the most bandwidth.
 

+ 3 - 0
Source/Engine/LuaScript/pkgs/Network/Connection.pkg

@@ -23,6 +23,7 @@ class Connection : public Object
     void SetIdentity(const VariantMap& identity);
     void SetControls(const Controls& newControls);
     void SetPosition(const Vector3& position);
+    void SetRotation(const Quaternion& rotation);
     void SetConnectPending(bool connectPending);
     void SetLogStatistics(bool enable);
     void Disconnect(int waitMSec = 0);
@@ -37,6 +38,7 @@ class Connection : public Object
     Scene* GetScene() const;
     const Controls& GetControls() const;
     const Vector3& GetPosition() const;
+    const Quaternion& GetRotation() const;
     bool IsClient() const;
     bool IsConnected() const;
     bool IsConnectPending() const;
@@ -53,6 +55,7 @@ class Connection : public Object
     tolua_property__get_set Scene* scene;
     tolua_property__get_set Controls& controls;
     tolua_property__get_set Vector3& position;
+    tolua_property__get_set Quaternion& rotation;
     tolua_readonly tolua_property__is_set bool client;
     tolua_readonly tolua_property__is_set bool connected;
     tolua_property__is_set bool connectPending;

+ 19 - 3
Source/Engine/Network/Connection.cpp

@@ -62,8 +62,8 @@ PackageUpload::PackageUpload() :
 
 Connection::Connection(Context* context, bool isClient, kNet::SharedPtr<kNet::MessageConnection> connection) :
     Object(context),
-    position_(Vector3::ZERO),
     connection_(connection),
+    sendMode_(OPSM_NONE),
     isClient_(isClient),
     connectPending_(false),
     sceneLoaded_(false),
@@ -206,6 +206,15 @@ void Connection::SetControls(const Controls& newControls)
 void Connection::SetPosition(const Vector3& position)
 {
     position_ = position;
+    if (sendMode_ == OPSM_NONE)
+        sendMode_ = OPSM_POSITION;
+}
+
+void Connection::SetRotation(const Quaternion& rotation)
+{
+    rotation_ = rotation;
+    if (sendMode_ != OPSM_POSITION_ROTATION)
+        sendMode_ = OPSM_POSITION_ROTATION;
 }
 
 void Connection::SetConnectPending(bool connectPending)
@@ -255,7 +264,10 @@ void Connection::SendClientUpdate()
     msg_.WriteFloat(controls_.yaw_);
     msg_.WriteFloat(controls_.pitch_);
     msg_.WriteVariantMap(controls_.extraData_);
-    msg_.WriteVector3(position_);
+    if (sendMode_ >= OPSM_POSITION)
+        msg_.WriteVector3(position_);
+    if (sendMode_ >= OPSM_POSITION_ROTATION)
+        msg_.WritePackedQuaternion(rotation_);
     SendMessage(MSG_CONTROLS, false, false, msg_, CONTROLS_CONTENT_ID);
 }
 
@@ -907,7 +919,11 @@ void Connection::ProcessControls(int msgID, MemoryBuffer& msg)
     newControls.extraData_ = msg.ReadVariantMap();
     
     SetControls(newControls);
-    SetPosition(msg.ReadVector3());
+    // Client may or may not send observer position & rotation for interest management
+    if (!msg.IsEof())
+        position_ = msg.ReadVector3();
+    if (!msg.IsEof())
+        rotation_ = msg.ReadPackedQuaternion();
 }
 
 void Connection::ProcessSceneLoaded(int msgID, MemoryBuffer& msg)

+ 20 - 4
Source/Engine/Network/Connection.h

@@ -92,6 +92,14 @@ struct PackageUpload
     unsigned totalFragments_;
 };
 
+/// Send modes for observer position/rotation. Activated by the client setting either position or rotation.
+enum ObserverPositionSendMode
+{
+    OPSM_NONE = 0,
+    OPSM_POSITION,
+    OPSM_POSITION_ROTATION
+};
+
 /// %Connection to a remote network host.
 class URHO3D_API Connection : public Object
 {
@@ -117,8 +125,10 @@ public:
     void SetIdentity(const VariantMap& identity);
     /// Set new controls.
     void SetControls(const Controls& newControls);
-    /// Set the observer position for interest management.
+    /// Set the observer position for interest management, to be sent to the server.
     void SetPosition(const Vector3& position);
+    /// Set the observer rotation for interest management, to be sent to the server. Note: not used by the NetworkPriority component.
+    void SetRotation(const Quaternion& rotation);
     /// Set the connection pending status. Called by Network.
     void SetConnectPending(bool connectPending);
     /// Set whether to log data in/out statistics.
@@ -146,8 +156,10 @@ public:
     Scene* GetScene() const;
     /// Return the client controls of this connection.
     const Controls& GetControls() const { return controls_; }
-    /// Return the observer position for interest management.
+    /// Return the observer position sent by the client for interest management.
     const Vector3& GetPosition() const { return position_; }
+    /// Return the observer rotation sent by the client for interest management.
+    const Quaternion& GetRotation() const { return rotation_; }
     /// Return whether is a client connection.
     bool IsClient() const { return isClient_; }
     /// Return whether is fully connected.
@@ -171,8 +183,6 @@ public:
     /// Return progress of current package download, or 1.0 if no downloads.
     float GetDownloadProgress() const;
     
-    /// Observer position for interest management.
-    Vector3 position_;
     /// Current controls.
     Controls controls_;
     /// Identity map.
@@ -242,6 +252,12 @@ private:
     String address_;
     /// Remote endpoint port.
     unsigned short port_;
+    /// Observer position for interest management.
+    Vector3 position_;
+    /// Observer rotation for interest management.
+    Quaternion rotation_;
+    /// Send mode for the observer position & rotation.
+    ObserverPositionSendMode sendMode_;
     /// Client connection flag.
     bool isClient_;
     /// Connection pending flag.

+ 4 - 1
Source/Engine/Script/NetworkAPI.cpp

@@ -107,7 +107,10 @@ static void RegisterConnection(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Connection", "uint get_numDownloads() const", asMETHOD(Connection, GetNumDownloads), asCALL_THISCALL);
     engine->RegisterObjectMethod("Connection", "const String& get_downloadName() const", asMETHOD(Connection, GetDownloadName), asCALL_THISCALL);
     engine->RegisterObjectMethod("Connection", "float get_downloadProgress() const", asMETHOD(Connection, GetDownloadProgress), asCALL_THISCALL);
-    engine->RegisterObjectProperty("Connection", "Vector3 position", offsetof(Connection, position_));
+    engine->RegisterObjectMethod("Connection", "void set_position(const Vector3&in)", asMETHOD(Connection, SetPosition), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Connection", "const Vector3& get_position() const", asMETHOD(Connection, GetPosition), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Connection", "void set_rotation(const Quaternion&in)", asMETHOD(Connection, SetRotation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Connection", "const Quaternion& get_rotation() const", asMETHOD(Connection, GetRotation), asCALL_THISCALL);
     engine->RegisterObjectProperty("Connection", "Controls controls", offsetof(Connection, controls_));
     engine->RegisterObjectProperty("Connection", "VariantMap identity", offsetof(Connection, identity_));