Browse Source

Added Abs() to Vector2, Vector3 and Vector4.
Compressed rotation and angular velocity to half size in network replication.

Lasse Öörni 14 năm trước cách đây
mục cha
commit
13d449d9cc

+ 2 - 0
Engine/Math/Vector2.h

@@ -170,6 +170,8 @@ public:
     float DotProduct(const Vector2& rhs) const { return x_ * rhs.x_ + y_ * rhs.y_; }
     /// Calculate absolute dot product
     float AbsDotProduct(const Vector2& rhs) const { return fabsf(x_ * rhs.x_) + fabsf(y_ * rhs.y_); }
+    /// Return absolute vector
+    Vector2 Abs() const { return Vector2(fabsf(x_), fabsf(y_)); }
     /// Linear interpolation with another vector
     Vector2 Lerp(const Vector2& rhs, float t) const { return *this * (1.0f - t) + rhs * t; }
     

+ 2 - 0
Engine/Math/Vector3.h

@@ -201,6 +201,8 @@ public:
         );
     }
     
+    /// Return absolute vector
+    Vector3 Abs() const { return Vector3(fabsf(x_), fabsf(y_), fabsf(z_)); }
     /// Linear interpolation with another vector
     Vector3 Lerp(const Vector3& rhs, float t) const { return *this * (1.0f - t) + rhs * t; }
     

+ 2 - 0
Engine/Math/Vector4.h

@@ -170,6 +170,8 @@ public:
     float DotProduct(const Vector4& rhs) const { return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_ + w_ * rhs.w_; }
     /// Calculate absolute dot product
     float AbsDotProduct(const Vector4& rhs) const { return fabsf(x_ * rhs.x_) + fabsf(y_ * rhs.y_) + fabsf(z_ * rhs.z_) + fabsf(w_ * rhs.w_); }
+    /// Return absolute vector
+    Vector4 Abs() const { return Vector4(fabsf(x_), fabsf(y_), fabsf(z_), fabsf(w_)); }
     /// Linear interpolation with another vector
     Vector4 Lerp(const Vector4& rhs, float t) const { return *this * (1.0f - t) + rhs * t; }
     

+ 2 - 2
Engine/Physics/Joint.cpp

@@ -65,8 +65,8 @@ void Joint::RegisterObject(Context* context)
     ENUM_ATTRIBUTE(Joint, "Joint Type", type_, typeNames, JOINT_NONE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Joint, VAR_INT, "Body A", GetBodyAAttr, SetBodyAAttr, int, 0, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Joint, VAR_INT, "Body B", GetBodyBAttr, SetBodyBAttr, int, 0, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Axis", GetAxis, SetAxis, Vector3, Vector3::ZERO, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
+    ACCESSOR_ATTRIBUTE(Joint, VAR_VECTOR3, "Axis", GetAxis, SetAxis, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
 }
 
 void Joint::OnSetAttribute(const AttributeInfo& attr, const Variant& src)

+ 14 - 8
Engine/Physics/PhysicsWorld.cpp

@@ -42,8 +42,8 @@
 #include "DebugNew.h"
 
 static const int DEFAULT_FPS = 60;
-static const int DEFAULT_MAXCONTACTS = 20;
-static const float DEFAULT_BOUNCETHRESHOLD = 0.1f;
+static const int DEFAULT_MAX_CONTACTS = 20;
+static const float DEFAULT_BOUNCE_THRESHOLD = 0.1f;
 
 static unsigned numInstances = 0;
 
@@ -61,8 +61,8 @@ PhysicsWorld::PhysicsWorld(Context* context) :
     rayGeometry_(0),
     contactJoints_(0),
     fps_(DEFAULT_FPS),
-    maxContacts_(DEFAULT_MAXCONTACTS),
-    bounceThreshold_(DEFAULT_BOUNCETHRESHOLD),
+    maxContacts_(DEFAULT_MAX_CONTACTS),
+    bounceThreshold_(DEFAULT_BOUNCE_THRESHOLD),
     timeAcc_(0.0f),
     randomSeed_(0)
 {
@@ -134,10 +134,11 @@ void PhysicsWorld::RegisterObject(Context* context)
     context->RegisterFactory<PhysicsWorld>();
     
     ATTRIBUTE(PhysicsWorld, VAR_INT, "Physics FPS", fps_, DEFAULT_FPS, AM_DEFAULT);
-    ATTRIBUTE(PhysicsWorld, VAR_INT, "Max Contacts", maxContacts_, DEFAULT_MAXCONTACTS, AM_DEFAULT);
-    ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Bounce Threshold", bounceThreshold_, DEFAULT_BOUNCETHRESHOLD, AM_DEFAULT);
-    ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Time Accumulator", timeAcc_, 0.0f, AM_DEFAULT);
-    ATTRIBUTE(PhysicsWorld, VAR_INT, "Random Seed", randomSeed_, 0, AM_DEFAULT);
+    ATTRIBUTE(PhysicsWorld, VAR_INT, "Max Contacts", maxContacts_, DEFAULT_MAX_CONTACTS, AM_DEFAULT);
+    ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Bounce Threshold", bounceThreshold_, DEFAULT_BOUNCE_THRESHOLD, AM_DEFAULT);
+    ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Max Network Angular Velocity", maxNetworkAngularVelocity_, DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY, AM_DEFAULT);
+    ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Time Accumulator", timeAcc_, 0.0f, AM_FILE | AM_NOEDIT);
+    ATTRIBUTE(PhysicsWorld, VAR_INT, "Random Seed", randomSeed_, 0, AM_FILE | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_VECTOR3, "Gravity", GetGravity, SetGravity, Vector3, Vector3::ZERO, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Linear Rest Threshold", GetLinearRestThreshold, SetLinearRestThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Linear Damping Threshold", GetLinearDampingThreshold, SetLinearDampingThreshold, float, 0.01f, AM_DEFAULT);
@@ -262,6 +263,11 @@ void PhysicsWorld::SetBounceThreshold(float threshold)
     bounceThreshold_ = Max(threshold, 0.0f);
 }
 
+void PhysicsWorld::SetMaxNetworkAngularVelocity(float velocity)
+{
+    maxNetworkAngularVelocity_ = Clamp(velocity, 1.0f, 32767.0f);
+}
+
 void PhysicsWorld::SetERP(float erp)
 {
     dWorldSetERP(physicsWorld_, erp);

+ 7 - 1
Engine/Physics/PhysicsWorld.h

@@ -84,7 +84,7 @@ struct PhysicsCollisionInfo
     PODVector<PhysicsContactInfo> contacts_;
 };
 
-static const float PHYSICS_MIN_TIMESTEP = 0.001f;
+static const float DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY = 100.0f;
 
 /// A physics simulation world
 class PhysicsWorld : public Component
@@ -121,6 +121,8 @@ public:
     void SetAngularDampingScale(float scale);
     /// Set collision bounce velocity threshold (apply bounce if above)
     void SetBounceThreshold(float threshold);
+    /// Set maximum angular velocity for network replication
+    void SetMaxNetworkAngularVelocity(float velocity);
     /// Set simulation ERP parameter
     void SetERP(float erp);
     /// Set simulation CFM parameter
@@ -157,6 +159,8 @@ public:
     float GetAngularDampingScale() const;
     /// Return collision bounce velocity threshold
     float GetBounceThreshold() const { return bounceThreshold_; }
+    /// Return maximum angular velocity for network replication
+    float GetMaxNetworkAngularVelocity() const { return maxNetworkAngularVelocity_; }
     /// Return simulation ERP parameter
     float GetERP() const;
     /// Return simulation CFM parameter
@@ -208,6 +212,8 @@ private:
     unsigned maxContacts_;
     /// Collision bounce velocity threshold
     float bounceThreshold_;
+    /// Maximum angular velocity for network replication
+    float maxNetworkAngularVelocity_;
     /// Simulation step time accumulator
     float timeAcc_;
     /// Simulation random seed

+ 22 - 3
Engine/Physics/RigidBody.cpp

@@ -25,6 +25,7 @@
 #include "CollisionShape.h"
 #include "Context.h"
 #include "Log.h"
+#include "MemoryBuffer.h"
 #include "PhysicsWorld.h"
 #include "ResourceCache.h"
 #include "ResourceEvents.h"
@@ -68,18 +69,19 @@ void RigidBody::RegisterObject(Context* context)
     context->RegisterFactory<RigidBody>();
     
     ATTRIBUTE(RigidBody, VAR_FLOAT, "Mass", mass_, DEFAULT_MASS, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Physics Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_FILE);
-    ACCESSOR_ATTRIBUTE(RigidBody, VAR_QUATERNION, "Physics Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE);
+    ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Physics Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_FILE | AM_NOEDIT);
+    ACCESSOR_ATTRIBUTE(RigidBody, VAR_QUATERNION, "Physics Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE | AM_NOEDIT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Linear Velocity", GetLinearVelocity, SetLinearVelocity, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Linear Rest Threshold", GetLinearRestThreshold, SetLinearRestThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Linear Damping Threshold", GetLinearDampingThreshold, SetLinearDampingThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Linear Damping Scale", GetLinearDampingScale, SetLinearDampingScale, float, 0.0f, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Angular Velocity", GetAngularVelocity, SetAngularVelocity, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
+    ACCESSOR_ATTRIBUTE(RigidBody, VAR_VECTOR3, "Angular Velocity", GetAngularVelocity, SetAngularVelocity, Vector3, Vector3::ZERO, AM_FILE);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Rest Threshold", GetAngularRestThreshold, SetAngularRestThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Damping Threshold", GetAngularDampingThreshold, SetAngularDampingThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Damping Scale", GetAngularDampingScale, SetAngularDampingScale, float, 0.0f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_FLOAT, "Angular Max Velocity", GetAngularMaxVelocity, SetAngularMaxVelocity, float, M_INFINITY, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(RigidBody, VAR_BOOL, "Is Active", IsActive, SetActive, bool, true, AM_FILE);
+    REF_ACCESSOR_ATTRIBUTE(RigidBody, VAR_BUFFER, "Network Angular Velocity", GetNetAngularVelocityAttr, SetNetAngularVelocityAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_NET | AM_LATESTDATA | AM_NOEDIT);
 }
 
 void RigidBody::SetMass(float mass)
@@ -333,6 +335,23 @@ bool RigidBody::IsActive() const
         return false;
 }
 
+void RigidBody::SetNetAngularVelocityAttr(const PODVector<unsigned char>& value)
+{
+    float maxVelocity = physicsWorld_ ? physicsWorld_->GetMaxNetworkAngularVelocity() : DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY;
+    
+    MemoryBuffer buf(value);
+    SetAngularVelocity(buf.ReadPackedVector3(maxVelocity));
+}
+
+const PODVector<unsigned char>& RigidBody::GetNetAngularVelocityAttr() const
+{
+    float maxVelocity = physicsWorld_ ? physicsWorld_->GetMaxNetworkAngularVelocity() : DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY;
+    
+    attrBuffer_.Clear();
+    attrBuffer_.WritePackedVector3(GetAngularVelocity(), maxVelocity);
+    return attrBuffer_.GetBuffer();
+}
+
 void RigidBody::OnMarkedDirty(Node* node)
 {
     // Clear the dirty flag by querying world position; this way we are sure to get the dirty notification immediately

+ 6 - 0
Engine/Physics/RigidBody.h

@@ -114,6 +114,10 @@ public:
     
     /// Recalculate mass
     void UpdateMass();
+    /// Set network angular velocity attribute
+    void SetNetAngularVelocityAttr(const PODVector<unsigned char>& value);
+    /// Return network angular velocity attribute
+    const PODVector<unsigned char>& GetNetAngularVelocityAttr() const;
     
 protected:
     /// Handle node being assigned
@@ -141,6 +145,8 @@ private:
     Vector3 previousPosition_;
     /// Previous rotation for rendering interpolation
     Quaternion previousRotation_;
+    /// Attribute buffer for network replication
+    mutable VectorBuffer attrBuffer_;
     /// Poststep flag
     bool inPostStep_;
 };

+ 25 - 11
Engine/Scene/Node.cpp

@@ -67,10 +67,11 @@ void Node::RegisterObject(Context* context)
     
     REF_ACCESSOR_ATTRIBUTE(Node, VAR_STRING, "Name", GetName, SetName, String, String(), AM_DEFAULT);
     REF_ACCESSOR_ATTRIBUTE(Node, VAR_VECTOR3, "Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
-    REF_ACCESSOR_ATTRIBUTE(Node, VAR_QUATERNION, "Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_DEFAULT | AM_LATESTDATA);
+    REF_ACCESSOR_ATTRIBUTE(Node, VAR_QUATERNION, "Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Node, VAR_VECTOR3, "Scale", GetScale, SetScale, Vector3, Vector3::UNITY, AM_DEFAULT);
-    REF_ACCESSOR_ATTRIBUTE(Node, VAR_BUFFER, "Parent Node", GetParentAttr, SetParentAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_NET | AM_NOEDIT);
-    ATTRIBUTE(Node, VAR_VARIANTMAP, "Variables", vars_, VariantMap(), AM_FILE);
+    ATTRIBUTE(Node, VAR_VARIANTMAP, "Variables", vars_, VariantMap(), AM_FILE); // Network replication of vars uses custom data
+    REF_ACCESSOR_ATTRIBUTE(Node, VAR_BUFFER, "Network Rotation", GetNetRotationAttr, SetNetRotationAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_NET | AM_LATESTDATA | AM_NOEDIT);
+    REF_ACCESSOR_ATTRIBUTE(Node, VAR_BUFFER, "Network Parent Node", GetNetParentAttr, SetNetParentAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_NET | AM_NOEDIT);
 }
 
 void Node::OnEvent(Object* sender, bool broadcast, StringHash eventType, VariantMap& eventData)
@@ -620,7 +621,13 @@ void Node::SetOwner(Connection* owner)
     owner_ = owner;
 }
 
-void Node::SetParentAttr(const PODVector<unsigned char>& value)
+void Node::SetNetRotationAttr(const PODVector<unsigned char>& value)
+{
+    MemoryBuffer buf(value);
+    SetRotation(buf.ReadPackedQuaternion());
+}
+
+void Node::SetNetParentAttr(const PODVector<unsigned char>& value)
 {
     Scene* scene = GetScene();
     if (!scene)
@@ -641,15 +648,22 @@ void Node::SetParentAttr(const PODVector<unsigned char>& value)
     }
 }
 
-const PODVector<unsigned char>& Node::GetParentAttr() const
+const PODVector<unsigned char>& Node::GetNetRotationAttr() const
+{
+    attrBuffer_.Clear();
+    attrBuffer_.WritePackedQuaternion(rotation_);
+    return attrBuffer_.GetBuffer();
+}
+
+const PODVector<unsigned char>& Node::GetNetParentAttr() const
 {
-    parentAttr_.Clear();
+    attrBuffer_.Clear();
     Scene* scene = GetScene();
     if (scene && parent_)
     {
         unsigned parentID = parent_->GetID();
         if (parentID < FIRST_LOCAL_ID)
-            parentAttr_.WriteVLE(parentID);
+            attrBuffer_.WriteVLE(parentID);
         else
         {
             // Parent is local: traverse hierarchy to find a non-local base node
@@ -658,14 +672,14 @@ const PODVector<unsigned char>& Node::GetParentAttr() const
             while (current->GetID() >= FIRST_LOCAL_ID)
                 current = current->GetParent();
             
-            parentAttr_.WriteVLE(current->GetID());
-            parentAttr_.WriteStringHash(parent_->GetNameHash());
+            attrBuffer_.WriteVLE(current->GetID());
+            attrBuffer_.WriteStringHash(parent_->GetNameHash());
         }
     }
     else
-        parentAttr_.WriteVLE(0);
+        attrBuffer_.WriteVLE(0);
     
-    return parentAttr_.GetBuffer();
+    return attrBuffer_.GetBuffer();
 }
 
 bool Node::Load(Deserializer& source, bool readChildren)

+ 10 - 7
Engine/Scene/Node.h

@@ -243,11 +243,14 @@ public:
     void SetScene(Scene* scene);
     /// Set owner connection for multiplayer
     void SetOwner(Connection* owner);
-    
-    /// Set parent attribute (network only)
-    void SetParentAttr(const PODVector<unsigned char>& value);
-    /// Return parent attribute (network only)
-    const PODVector<unsigned char>& GetParentAttr() const;
+    /// Set network rotation attribute
+    void SetNetRotationAttr(const PODVector<unsigned char>& value);
+    /// Set network parent attribute
+    void SetNetParentAttr(const PODVector<unsigned char>& value);
+    /// Return network rotation attribute
+    const PODVector<unsigned char>& GetNetRotationAttr() const;
+    /// Return network parent attribute
+    const PODVector<unsigned char>& GetNetParentAttr() const;
     
     /// User variables
     VariantMap vars_;
@@ -298,8 +301,8 @@ private:
     Vector<SharedPtr<Component> > components_;
     /// Node listeners
     Vector<WeakPtr<Component> > listeners_;
-    /// Parent attribute buffer for network replication
-    mutable VectorBuffer parentAttr_;
+    /// Attribute buffer for network replication
+    mutable VectorBuffer attrBuffer_;
     /// Consecutive rotation count for rotation renormalization
     unsigned char rotateCount_;
     /// World transform needs update flag