Browse Source

Fixed enemy motion bugs in networked NinjaSnowWar.
Added possibility to disable physics interpolation. This is useful on a network server to ensure clients do not receive interpolated (and possibly non-physical) node transforms.
Changed default network update FPS to 30 (half of the default physics FPS.)

Lasse Öörni 14 years ago
parent
commit
26e2ebca26

+ 111 - 111
Bin/Data/Objects/Ninja.xml

@@ -1,111 +1,111 @@
-<node id="6">
-    <attribute name="Name" value="Ninja" />
-    <attribute name="Position" value="0 0 0" />
-    <attribute name="Rotation" value="1 0 0 0" />
-    <attribute name="Scale" value="1 1 1" />
-    <attribute name="Variables" />
-    <component type="ScriptInstance" id="16777216">
-        <attribute name="Script File" value="ScriptFile;Scripts/NinjaSnowWar.as" />
-        <attribute name="Class Name" value="Ninja" />
-        <attribute name="Is Active" value="true" />
-        <attribute name="Fixed Update FPS" value="0" />
-        <attribute name="Time Accumulator" value="0" />
-        <attribute name="Delayed Method Calls" value="0" />
-        <attribute name="Script Data" value="" />
-    </component>
-    <component type="NetworkPriority" id="16777217">
-        <attribute name="Base Priority" value="110" />
-        <attribute name="Distance Factor" value="0.03" />
-        <attribute name="Minimum Priority" value="20" />
-        <attribute name="Always Update Owner" value="true" />
-    </component>
-    <component type="CollisionShape" id="11">
-        <attribute name="Shape Type" type="Enum" value="Capsule" />
-        <attribute name="Size" value="70 180 70" />
-        <attribute name="Offset Position" value="0 0 0" />
-        <attribute name="Offset Rotation" value="1 0 0 0" />
-        <attribute name="Model" value="Model;" />
-        <attribute name="LOD Level" value="0" />
-        <attribute name="Hull Thickness" value="0" />
-        <attribute name="Friction" value="0.5" />
-        <attribute name="Bounce" value="0" />
-        <attribute name="Collision Group" value="1" />
-        <attribute name="Collision Mask" value="3" />
-        <attribute name="Is Phantom" value="false" />
-    </component>
-    <component type="RigidBody" id="12">
-        <attribute name="Mass" value="80" />
-        <attribute name="Mass Axis" value="1" />
-        <attribute name="Physics Position" value="0 0 0" />
-        <attribute name="Physics Rotation" value="1 0 0 0" />
-        <attribute name="Linear Velocity" value="0 0 0" />
-        <attribute name="Angular Velocity" value="0 0 0" />
-        <attribute name="Lin Rest Threshold" value="0.1" />
-        <attribute name="Lin Damp Threshold" value="0" />
-        <attribute name="Lin Damp Scale" value="0.001" />
-        <attribute name="Ang Rest Threshold" value="0.01" />
-        <attribute name="Ang Damp Threshold" value="0.01" />
-        <attribute name="Ang Damp Scale" value="0" />
-        <attribute name="Ang Max Velocity" value="0" />
-        <attribute name="Is Active" value="true" />
-    </component>
-    <node id="7">
-        <attribute name="Name" value="" />
-        <attribute name="Position" value="0 -90 0" />
-        <attribute name="Rotation" value="1 0 0 0" />
-        <attribute name="Scale" value="1 1 1" />
-        <attribute name="Variables" />
-        <component type="AnimatedModel" id="9">
-            <attribute name="Model" value="Model;Models/Ninja.mdl" />
-            <attribute name="Material" value="Material;Materials/Ninja.xml;Materials/Ninja.xml" />
-            <attribute name="Is Visible" value="true" />
-            <attribute name="Is Occluder" value="false" />
-            <attribute name="Can Be Occluded" value="true" />
-            <attribute name="Cast Shadows" value="true" />
-            <attribute name="Draw Distance" value="15000" />
-            <attribute name="Shadow Distance" value="0" />
-            <attribute name="LOD Bias" value="1" />
-            <attribute name="Animation LOD Bias" value="1" />
-            <attribute name="Max Lights" value="0" />
-            <attribute name="View Mask" value="-1" />
-            <attribute name="Light Mask" value="-1" />
-            <attribute name="Shadow Mask" value="-1" />
-            <attribute name="Zone Mask" value="-1" />
-            <attribute name="Ray/Occl. LOD Level" value="-1" />
-            <attribute name="Bone Animation Enabled">
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-                <variant type="Bool" value="true" />
-            </attribute>
-            <attribute name="Animation States" />
-        </component>
-        <component type="AnimationController" id="10">
-            <attribute name="Animations" />
-        </component>
-    </node>
-</node>
+<node id="6">
+    <attribute name="Name" value="Ninja" />
+    <attribute name="Position" value="0 0 0" />
+    <attribute name="Rotation" value="1 0 0 0" />
+    <attribute name="Scale" value="1 1 1" />
+    <attribute name="Variables" />
+    <component type="ScriptInstance" id="16777216">
+        <attribute name="Script File" value="ScriptFile;Scripts/NinjaSnowWar.as" />
+        <attribute name="Class Name" value="Ninja" />
+        <attribute name="Is Active" value="true" />
+        <attribute name="Fixed Update FPS" value="0" />
+        <attribute name="Time Accumulator" value="0" />
+        <attribute name="Delayed Method Calls" value="0" />
+        <attribute name="Script Data" value="" />
+    </component>
+    <component type="NetworkPriority" id="16777217">
+        <attribute name="Base Priority" value="110" />
+        <attribute name="Distance Factor" value="0.02" />
+        <attribute name="Minimum Priority" value="50" />
+        <attribute name="Always Update Owner" value="true" />
+    </component>
+    <component type="CollisionShape" id="11">
+        <attribute name="Shape Type" type="Enum" value="Capsule" />
+        <attribute name="Size" value="70 180 70" />
+        <attribute name="Offset Position" value="0 0 0" />
+        <attribute name="Offset Rotation" value="1 0 0 0" />
+        <attribute name="Model" value="Model;" />
+        <attribute name="LOD Level" value="0" />
+        <attribute name="Hull Thickness" value="0" />
+        <attribute name="Friction" value="0.5" />
+        <attribute name="Bounce" value="0" />
+        <attribute name="Collision Group" value="1" />
+        <attribute name="Collision Mask" value="3" />
+        <attribute name="Is Phantom" value="false" />
+    </component>
+    <component type="RigidBody" id="12">
+        <attribute name="Mass" value="80" />
+        <attribute name="Mass Axis" value="1" />
+        <attribute name="Physics Position" value="0 0 0" />
+        <attribute name="Physics Rotation" value="1 0 0 0" />
+        <attribute name="Linear Velocity" value="0 0 0" />
+        <attribute name="Angular Velocity" value="0 0 0" />
+        <attribute name="Lin Rest Threshold" value="0.1" />
+        <attribute name="Lin Damp Threshold" value="0" />
+        <attribute name="Lin Damp Scale" value="0.001" />
+        <attribute name="Ang Rest Threshold" value="0.01" />
+        <attribute name="Ang Damp Threshold" value="0.01" />
+        <attribute name="Ang Damp Scale" value="0" />
+        <attribute name="Ang Max Velocity" value="0" />
+        <attribute name="Is Active" value="true" />
+    </component>
+    <node id="7">
+        <attribute name="Name" value="" />
+        <attribute name="Position" value="0 -90 0" />
+        <attribute name="Rotation" value="1 0 0 0" />
+        <attribute name="Scale" value="1 1 1" />
+        <attribute name="Variables" />
+        <component type="AnimatedModel" id="9">
+            <attribute name="Model" value="Model;Models/Ninja.mdl" />
+            <attribute name="Material" value="Material;Materials/Ninja.xml;Materials/Ninja.xml" />
+            <attribute name="Is Visible" value="true" />
+            <attribute name="Is Occluder" value="false" />
+            <attribute name="Can Be Occluded" value="true" />
+            <attribute name="Cast Shadows" value="true" />
+            <attribute name="Draw Distance" value="15000" />
+            <attribute name="Shadow Distance" value="0" />
+            <attribute name="LOD Bias" value="1" />
+            <attribute name="Animation LOD Bias" value="1" />
+            <attribute name="Max Lights" value="0" />
+            <attribute name="View Mask" value="-1" />
+            <attribute name="Light Mask" value="-1" />
+            <attribute name="Shadow Mask" value="-1" />
+            <attribute name="Zone Mask" value="-1" />
+            <attribute name="Ray/Occl. LOD Level" value="-1" />
+            <attribute name="Bone Animation Enabled">
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+                <variant type="Bool" value="true" />
+            </attribute>
+            <attribute name="Animation States" />
+        </component>
+        <component type="AnimationController" id="10">
+            <attribute name="Animations" />
+        </component>
+    </node>
+</node>

+ 4 - 0
Bin/Data/Scripts/NinjaSnowWar.as

@@ -133,6 +133,7 @@ void InitScene()
 
 
 void InitNetworking()
 void InitNetworking()
 {
 {
+    network.updateFps = 25; // 1/4 of physics FPS
     network.RegisterRemoteEvent("PlayerSpawned");
     network.RegisterRemoteEvent("PlayerSpawned");
     network.RegisterRemoteEvent("UpdateScore");
     network.RegisterRemoteEvent("UpdateScore");
     network.RegisterRemoteEvent("UpdateHiscores");
     network.RegisterRemoteEvent("UpdateHiscores");
@@ -141,6 +142,9 @@ void InitNetworking()
     {
     {
         network.StartServer(serverPort);
         network.StartServer(serverPort);
 
 
+        // Disable physics interpolation to ensure clients get sent physically correct transforms
+        gameScene.physicsWorld.interpolation = false;
+
         SubscribeToEvent("ClientIdentity", "HandleClientIdentity");
         SubscribeToEvent("ClientIdentity", "HandleClientIdentity");
         SubscribeToEvent("ClientSceneLoaded", "HandleClientSceneLoaded");
         SubscribeToEvent("ClientSceneLoaded", "HandleClientSceneLoaded");
         SubscribeToEvent("ClientDisconnected", "HandleClientDisconnected");
         SubscribeToEvent("ClientDisconnected", "HandleClientDisconnected");

+ 3 - 0
Bin/Data/Scripts/TestScene.as

@@ -40,6 +40,9 @@ void Start()
         network.StartServer(serverPort);
         network.StartServer(serverPort);
         SubscribeToEvent("ClientConnected", "HandleClientConnected");
         SubscribeToEvent("ClientConnected", "HandleClientConnected");
 
 
+        // Disable physics interpolation to ensure clients get sent physically correct transforms
+        testScene.physicsWorld.interpolation = false;
+
         // Test package download by adding all package files in the cache as requirements for the scene
         // Test package download by adding all package files in the cache as requirements for the scene
         Array<PackageFile@> packages = cache.packageFiles;
         Array<PackageFile@> packages = cache.packageFiles;
         for (uint i = 0; i < packages.length; ++i)
         for (uint i = 0; i < packages.length; ++i)

+ 4 - 2
Docs/Reference.dox

@@ -1104,7 +1104,7 @@ The default flags are AM_FILE and AM_NET.
 
 
 The Network library provides reliable and unreliable UDP messaging using kNet. A server can be created that listens for incoming connections, and client connections can be made to the server. After connecting, code running on the server can assign the client into a scene to enable scene replication, provided that when connecting, the client specified a blank scene for receiving the updates.
 The Network library provides reliable and unreliable UDP messaging using kNet. A server can be created that listens for incoming connections, and client connections can be made to the server. After connecting, code running on the server can assign the client into a scene to enable scene replication, provided that when connecting, the client specified a blank scene for receiving the updates.
 
 
-%Scene replication is one-directional: the server always has authority and sends scene updates to the client at a fixed update rate, by default 25 FPS. The client responds by sending controls updates (buttons, yaw and pitch + possible extra data) also at a fixed rate.
+%Scene replication is one-directional: the server always has authority and sends scene updates to the client at a fixed update rate, by default 30 FPS. The client responds by sending controls updates (buttons, yaw and pitch + possible extra data) also at a fixed rate.
 
 
 Bidirectional communication between the server and the client can happen either using raw network messages, which are binary-serialized data, or remote events, which operate like ordinary events, but are processed on the receiving end only. Code on the server can send messages or remote events either to one client, all clients assigned into a particular scene, or to all connected clients. In contrast the client can only send messages or remote events to the server, not directly to other clients.
 Bidirectional communication between the server and the client can happen either using raw network messages, which are binary-serialized data, or remote events, which operate like ordinary events, but are processed on the receiving end only. Code on the server can send messages or remote events either to one client, all clients assigned into a particular scene, or to all connected clients. In contrast the client can only send messages or remote events to the server, not directly to other clients.
 
 
@@ -1138,6 +1138,8 @@ There are some things to watch out for:
 
 
 - Position and rotation are Node attributes, while linear and angular velocities are RigidBody attributes. To cut down on the needed network bandwidth the physics components can be created as local on the server: in this case the client will not see them at all, and will only interpolate motion based on the node's transform changes. Replicating the actual physics components allows the client to extrapolate using its own physics simulation, and to also perform collision detection, though always non-authoritatively.
 - Position and rotation are Node attributes, while linear and angular velocities are RigidBody attributes. To cut down on the needed network bandwidth the physics components can be created as local on the server: in this case the client will not see them at all, and will only interpolate motion based on the node's transform changes. Replicating the actual physics components allows the client to extrapolate using its own physics simulation, and to also perform collision detection, though always non-authoritatively.
 
 
+- By default the physics simulation also performs interpolation to enable smooth motion when the rendering framerate is higher than the physics FPS. This should be disabled on the server scene to ensure that the clients do not receive interpolated and therefore possibly non-physical positions and rotations. See \ref PhysicsWorld::SetInterpolation "SetInterpolation()".
+
 - AnimatedModel does not replicate animation by itself. Rather, AnimationController will replicate its command state (such as "fade this animation in, play that animation at 1.5x speed.") To turn off animation replication, create the AnimationController as local. To ensure that also the first animation update will be received correctly, always create the AnimatedModel component first, then the AnimationController.
 - AnimatedModel does not replicate animation by itself. Rather, AnimationController will replicate its command state (such as "fade this animation in, play that animation at 1.5x speed.") To turn off animation replication, create the AnimationController as local. To ensure that also the first animation update will be received correctly, always create the AnimatedModel component first, then the AnimationController.
 
 
 - Networked attributes can either be in delta update or latest data mode. Delta updates are small incremental changes and must be applied in order, which may cause increased latency if there is a stall in network message delivery eg. due to packet loss. High volume data such as position, rotation and velocities are transmitted as latest data, which does not need ordering, instead this mode simply discards any old data received out of order. Note that node and component creation (when initial attributes need to be sent) and removal can also be considered as delta updates and are therefore applied in order.
 - Networked attributes can either be in delta update or latest data mode. Delta updates are small incremental changes and must be applied in order, which may cause increased latency if there is a stall in network message delivery eg. due to packet loss. High volume data such as position, rotation and velocities are transmitted as latest data, which does not need ordering, instead this mode simply discards any old data received out of order. Note that node and component creation (when initial attributes need to be sent) and removal can also be considered as delta updates and are therefore applied in order.
@@ -1164,7 +1166,7 @@ For now, creation and removal of nodes is always sent immediately, without consu
 
 
 \section Network_Controls Client controls update
 \section Network_Controls Client controls update
 
 
-The Controls structure is used to send controls information from the client to the server, by default also at 25 FPS. This includes held down buttons, which is an application-defined 32-bit bitfield, floating point yaw and pitch, and possible extra data (for example the currently selected weapon) stored within a VariantMap.
+The Controls structure is used to send controls information from the client to the server, by default also at 30 FPS. This includes held down buttons, which is an application-defined 32-bit bitfield, floating point yaw and pitch, and possible extra data (for example the currently selected weapon) stored within a VariantMap.
 
 
 It is up to the client code to ensure they are kept up-to-date, by calling \ref Connection::SetControls "SetControls()" on the server connection. The event E_NETWORKUPDDATE will be sent to remind of the impending update, and the event E_NETWORKUPDATESENT will be sent after the update. The controls can then be inspected on the server side by calling \ref Connection::GetControls "GetControls()".
 It is up to the client code to ensure they are kept up-to-date, by calling \ref Connection::SetControls "SetControls()" on the server connection. The event E_NETWORKUPDDATE will be sent to remind of the impending update, and the event E_NETWORKUPDATESENT will be sent after the update. The controls can then be inspected on the server side by calling \ref Connection::GetControls "GetControls()".
 
 

+ 3 - 2
Docs/ScriptAPI.dox

@@ -1275,7 +1275,7 @@ Properties:<br>
 - Matrix3x4 transform (readonly)
 - Matrix3x4 transform (readonly)
 - Matrix3x4 targetTransform (readonly)
 - Matrix3x4 targetTransform (readonly)
 - Matrix3x4& worldTransform (readonly)
 - Matrix3x4& worldTransform (readonly)
-- bool smoothed
+- bool smoothing
 - uint id (readonly)
 - uint id (readonly)
 - uint numChildren (readonly)
 - uint numChildren (readonly)
 - uint numAllChildren (readonly)
 - uint numAllChildren (readonly)
@@ -1382,7 +1382,7 @@ Properties:<br>
 - Matrix3x4 transform (readonly)
 - Matrix3x4 transform (readonly)
 - Matrix3x4 targetTransform (readonly)
 - Matrix3x4 targetTransform (readonly)
 - Matrix3x4& worldTransform (readonly)
 - Matrix3x4& worldTransform (readonly)
-- bool smoothed
+- bool smoothing
 - uint id (readonly)
 - uint id (readonly)
 - uint numChildren (readonly)
 - uint numChildren (readonly)
 - uint numAllChildren (readonly)
 - uint numAllChildren (readonly)
@@ -4058,6 +4058,7 @@ Properties:<br>
 - Vector3 gravity
 - Vector3 gravity
 - int fps
 - int fps
 - uint maxContacts
 - uint maxContacts
+- bool interpolation
 - float linearRestThreshold
 - float linearRestThreshold
 - float angularRestThreshold
 - float angularRestThreshold
 - float bounceThreshold
 - float bounceThreshold

+ 2 - 2
Engine/Engine/APITemplates.h

@@ -557,8 +557,8 @@ template <class T> void RegisterNode(asIScriptEngine* engine, const char* classN
     engine->RegisterObjectMethod(className, "Matrix3x4 get_transform() const", asMETHOD(T, GetTransform), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "Matrix3x4 get_transform() const", asMETHOD(T, GetTransform), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "Matrix3x4 get_targetTransform() const", asMETHOD(T, GetTargetTransform), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "Matrix3x4 get_targetTransform() const", asMETHOD(T, GetTargetTransform), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "const Matrix3x4& get_worldTransform() const", asMETHOD(T, GetWorldTransform), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "const Matrix3x4& get_worldTransform() const", asMETHOD(T, GetWorldTransform), asCALL_THISCALL);
-    engine->RegisterObjectMethod(className, "void set_smoothed(bool)", asMETHOD(T, SetSmoothed), asCALL_THISCALL);
-    engine->RegisterObjectMethod(className, "bool get_smoothed() const", asMETHOD(T, IsSmoothed), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_smoothing(bool)", asMETHOD(T, SetSmoothing), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_smoothing() const", asMETHOD(T, GetSmoothing), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "uint get_id()", asMETHOD(T, GetID), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "uint get_id()", asMETHOD(T, GetID), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "uint get_numChildren() const", asFUNCTION(NodeGetNumChildrenNonRecursive), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "uint get_numChildren() const", asFUNCTION(NodeGetNumChildrenNonRecursive), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "uint get_numAllChildren() const", asFUNCTION(NodeGetNumChildrenRecursive), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "uint get_numAllChildren() const", asFUNCTION(NodeGetNumChildrenRecursive), asCALL_CDECL_OBJLAST);

+ 2 - 0
Engine/Engine/PhysicsAPI.cpp

@@ -185,6 +185,8 @@ static void RegisterPhysicsWorld(asIScriptEngine* engine)
     engine->RegisterObjectMethod("PhysicsWorld", "int get_fps() const", asMETHOD(PhysicsWorld, GetFps), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "int get_fps() const", asMETHOD(PhysicsWorld, GetFps), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "void set_maxContacts(uint)", asMETHOD(PhysicsWorld, SetMaxContacts), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "void set_maxContacts(uint)", asMETHOD(PhysicsWorld, SetMaxContacts), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "uint get_maxContacts() const", asMETHOD(PhysicsWorld, GetMaxContacts), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "uint get_maxContacts() const", asMETHOD(PhysicsWorld, GetMaxContacts), asCALL_THISCALL);
+    engine->RegisterObjectMethod("PhysicsWorld", "void set_interpolation(bool)", asMETHOD(PhysicsWorld, SetInterpolation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("PhysicsWorld", "bool get_interpolation() const", asMETHOD(PhysicsWorld, GetInterpolation), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "void set_linearRestThreshold(float)", asMETHOD(PhysicsWorld, SetLinearRestThreshold), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "void set_linearRestThreshold(float)", asMETHOD(PhysicsWorld, SetLinearRestThreshold), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "float get_linearRestThreshold() const", asMETHOD(PhysicsWorld, GetLinearRestThreshold), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "float get_linearRestThreshold() const", asMETHOD(PhysicsWorld, GetLinearRestThreshold), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "void set_angularRestThreshold(float)", asMETHOD(PhysicsWorld, SetAngularRestThreshold), asCALL_THISCALL);
     engine->RegisterObjectMethod("PhysicsWorld", "void set_angularRestThreshold(float)", asMETHOD(PhysicsWorld, SetAngularRestThreshold), asCALL_THISCALL);

+ 3 - 3
Engine/Network/Connection.cpp

@@ -149,7 +149,7 @@ void Connection::SetScene(Scene* newScene)
     {
     {
         // Disable smoothing in case scene is no longer used for networking
         // Disable smoothing in case scene is no longer used for networking
         if (!isClient_)
         if (!isClient_)
-            scene_->SetSmoothed(false);
+            scene_->SetSmoothing(false);
         // Reset the owner reference from the previous scene's nodes
         // Reset the owner reference from the previous scene's nodes
         scene_->ResetOwner(this);
         scene_->ResetOwner(this);
     }
     }
@@ -183,7 +183,7 @@ void Connection::SetScene(Scene* newScene)
     else
     else
     {
     {
         // Enable motion smoothing on the client network scene
         // Enable motion smoothing on the client network scene
-        scene_->SetSmoothed(true);
+        scene_->SetSmoothing(true);
         // Make sure there is no existing async loading
         // Make sure there is no existing async loading
         scene_->StopAsyncLoading();
         scene_->StopAsyncLoading();
         SubscribeToEvent(scene_, E_ASYNCLOADFINISHED, HANDLER(Connection, HandleAsyncLoadFinished));
         SubscribeToEvent(scene_, E_ASYNCLOADFINISHED, HANDLER(Connection, HandleAsyncLoadFinished));
@@ -507,7 +507,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
             }
             }
             
             
             // Enable motion smoothing on the node
             // Enable motion smoothing on the node
-            node->SetSmoothed(true);
+            node->SetSmoothing(true);
             
             
             // Read initial attributes, then snap the motion smoothing immediately to the end
             // Read initial attributes, then snap the motion smoothing immediately to the end
             node->ReadDeltaUpdate(msg, deltaUpdateBits_);
             node->ReadDeltaUpdate(msg, deltaUpdateBits_);

+ 1 - 1
Engine/Network/Network.cpp

@@ -39,7 +39,7 @@
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
 
 
-static const int DEFAULT_UPDATE_FPS = 25;
+static const int DEFAULT_UPDATE_FPS = 30;
 
 
 OBJECTTYPESTATIC(Network);
 OBJECTTYPESTATIC(Network);
 
 

+ 1 - 1
Engine/Physics/CollisionShape.cpp

@@ -600,7 +600,7 @@ void CollisionShape::UpdateTransform(bool nodeUpdate)
     else
     else
     {
     {
         // No rigid body. Must update the geometry transform manually
         // No rigid body. Must update the geometry transform manually
-        // Use the target transform in case the node has smoothed motion enabled
+        // Use the target transform in case the node has smoothing enabled
         Matrix3x4 transform(node_->GetWorldTargetTransform());
         Matrix3x4 transform(node_->GetWorldTargetTransform());
         Vector3 nodePos(transform.Translation());
         Vector3 nodePos(transform.Translation());
         Quaternion nodeRot(transform.Rotation());
         Quaternion nodeRot(transform.Rotation());

+ 11 - 4
Engine/Physics/PhysicsWorld.cpp

@@ -63,10 +63,11 @@ PhysicsWorld::PhysicsWorld(Context* context) :
     contactJoints_(0),
     contactJoints_(0),
     fps_(DEFAULT_FPS),
     fps_(DEFAULT_FPS),
     maxContacts_(DEFAULT_MAX_CONTACTS),
     maxContacts_(DEFAULT_MAX_CONTACTS),
+    randomSeed_(0),
     bounceThreshold_(DEFAULT_BOUNCE_THRESHOLD),
     bounceThreshold_(DEFAULT_BOUNCE_THRESHOLD),
     maxNetworkAngularVelocity_(DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY),
     maxNetworkAngularVelocity_(DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY),
     timeAcc_(0.0f),
     timeAcc_(0.0f),
-    randomSeed_(0)
+    interpolation_(true)
 {
 {
     {
     {
         MutexLock lock(GetStaticMutex());
         MutexLock lock(GetStaticMutex());
@@ -155,8 +156,7 @@ void PhysicsWorld::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_VECTOR3, "Gravity", GetGravity, SetGravity, Vector3, Vector3::ZERO, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_VECTOR3, "Gravity", GetGravity, SetGravity, Vector3, Vector3::ZERO, AM_DEFAULT);
     ATTRIBUTE(PhysicsWorld, VAR_INT, "Physics FPS", fps_, DEFAULT_FPS, AM_DEFAULT);
     ATTRIBUTE(PhysicsWorld, VAR_INT, "Physics FPS", fps_, DEFAULT_FPS, AM_DEFAULT);
     ATTRIBUTE(PhysicsWorld, VAR_INT, "Max Contacts", maxContacts_, DEFAULT_MAX_CONTACTS, 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, "Network Max Ang Vel.", maxNetworkAngularVelocity_, DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY, AM_DEFAULT);
+    ATTRIBUTE(PhysicsWorld, VAR_BOOL, "Interpolation", interpolation_, true, AM_FILE);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Lin Rest Threshold", GetLinearRestThreshold, SetLinearRestThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Lin Rest Threshold", GetLinearRestThreshold, SetLinearRestThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Lin Damp Threshold", GetLinearDampingThreshold, SetLinearDampingThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Lin Damp Threshold", GetLinearDampingThreshold, SetLinearDampingThreshold, float, 0.01f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Lin Damp Scale", GetLinearDampingScale, SetLinearDampingScale, float, 0.0f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Lin Damp Scale", GetLinearDampingScale, SetLinearDampingScale, float, 0.0f, AM_DEFAULT);
@@ -166,6 +166,8 @@ void PhysicsWorld::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "ERP Parameter", GetERP, SetERP, float, 0.2f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "ERP Parameter", GetERP, SetERP, float, 0.2f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "CFM Parameter", GetCFM, SetCFM, float, 0.00001f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "CFM Parameter", GetCFM, SetCFM, float, 0.00001f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Contact Surface Layer", GetContactSurfaceLayer, SetContactSurfaceLayer, float, 0.0f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Contact Surface Layer", GetContactSurfaceLayer, SetContactSurfaceLayer, float, 0.0f, AM_DEFAULT);
+    ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Bounce Threshold", bounceThreshold_, DEFAULT_BOUNCE_THRESHOLD, AM_DEFAULT);
+    ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Network Max Ang Vel.", maxNetworkAngularVelocity_, DEFAULT_MAX_NETWORK_ANGULAR_VELOCITY, AM_DEFAULT);
     ATTRIBUTE(PhysicsWorld, VAR_FLOAT, "Time Accumulator", timeAcc_, 0.0f, AM_FILE | AM_NOEDIT);
     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);
     ATTRIBUTE(PhysicsWorld, VAR_INT, "Random Seed", randomSeed_, 0, AM_FILE | AM_NOEDIT);
 }
 }
@@ -226,7 +228,7 @@ void PhysicsWorld::Update(float timeStep)
     
     
     // Interpolate transforms of physics objects
     // Interpolate transforms of physics objects
     processedBodies_.Clear();
     processedBodies_.Clear();
-    float t = Clamp(timeAcc_ / internalTimeStep, 0.0f, 1.0f);
+    float t = interpolation_ ? Clamp(timeAcc_ / internalTimeStep, 0.0f, 1.0f) : 1.0f;
     for (PODVector<RigidBody*>::Iterator i = rigidBodies_.Begin(); i != rigidBodies_.End(); ++i)
     for (PODVector<RigidBody*>::Iterator i = rigidBodies_.Begin(); i != rigidBodies_.End(); ++i)
         (*i)->PostStep(t, processedBodies_);
         (*i)->PostStep(t, processedBodies_);
 }
 }
@@ -248,6 +250,11 @@ void PhysicsWorld::SetGravity(Vector3 gravity)
     dWorldSetGravity(physicsWorld_, gravity.x_, gravity.y_, gravity.z_);
     dWorldSetGravity(physicsWorld_, gravity.x_, gravity.y_, gravity.z_);
 }
 }
 
 
+void PhysicsWorld::SetInterpolation(bool enable)
+{
+    interpolation_ = enable;
+}
+
 void PhysicsWorld::SetLinearRestThreshold(float threshold)
 void PhysicsWorld::SetLinearRestThreshold(float threshold)
 {
 {
     dWorldSetAutoDisableLinearThreshold(physicsWorld_, Max(threshold, 0.0f));
     dWorldSetAutoDisableLinearThreshold(physicsWorld_, Max(threshold, 0.0f));

+ 20 - 14
Engine/Physics/PhysicsWorld.h

@@ -108,6 +108,8 @@ public:
     void SetMaxContacts(unsigned num);
     void SetMaxContacts(unsigned num);
     /// %Set gravity.
     /// %Set gravity.
     void SetGravity(Vector3 gravity);
     void SetGravity(Vector3 gravity);
+    /// %Set whether to interpolate between simulation steps.
+    void SetInterpolation(bool enable);
     /// %Set default linear velocity deactivation threshold for new rigid bodies.
     /// %Set default linear velocity deactivation threshold for new rigid bodies.
     void SetLinearRestThreshold(float threshold);
     void SetLinearRestThreshold(float threshold);
     /// %Set default linear velocity damping threshold.
     /// %Set default linear velocity damping threshold.
@@ -142,6 +144,8 @@ public:
     dSpaceID GetSpace() const { return space_; }
     dSpaceID GetSpace() const { return space_; }
     /// Return gravity.
     /// Return gravity.
     Vector3 GetGravity() const;
     Vector3 GetGravity() const;
+    /// Return whether interpolation between simulation steps is enabled.
+    bool GetInterpolation() const { return interpolation_; }
     /// Return simulation steps per second.
     /// Return simulation steps per second.
     int GetFps() const { return fps_; }
     int GetFps() const { return fps_; }
     /// Return maximum contacts per collision.
     /// Return maximum contacts per collision.
@@ -217,38 +221,40 @@ private:
     dGeomID rayGeometry_;
     dGeomID rayGeometry_;
     /// ODE contact joint group ID.
     /// ODE contact joint group ID.
     dJointGroupID contactJoints_;
     dJointGroupID contactJoints_;
-    /// Simulation steps per second.
-    unsigned fps_;
-    /// Maximum contacts per collision.
-    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.
-    unsigned randomSeed_;
     /// Rigid bodies in the world.
     /// Rigid bodies in the world.
     PODVector<RigidBody*> rigidBodies_;
     PODVector<RigidBody*> rigidBodies_;
     /// Collision shapes in the world.
     /// Collision shapes in the world.
     PODVector<CollisionShape*> collisionShapes_;
     PODVector<CollisionShape*> collisionShapes_;
     /// Joints in the world.
     /// Joints in the world.
     PODVector<Joint*> joints_;
     PODVector<Joint*> joints_;
-    /// Collision contacts (PODVector<dContact>.)
-    void* contacts_;
     /// Collision pairs on this frame.
     /// Collision pairs on this frame.
     HashSet<Pair<RigidBody*, RigidBody*> > currentCollisions_;
     HashSet<Pair<RigidBody*, RigidBody*> > currentCollisions_;
     /// Collision pairs on the previous frame. Used to check if a collision is "new."
     /// Collision pairs on the previous frame. Used to check if a collision is "new."
     HashSet<Pair<RigidBody*, RigidBody*> > previousCollisions_;
     HashSet<Pair<RigidBody*, RigidBody*> > previousCollisions_;
     /// Already processed rigid bodies during a poststep.
     /// Already processed rigid bodies during a poststep.
     HashSet<RigidBody*> processedBodies_;
     HashSet<RigidBody*> processedBodies_;
+    /// Collision contacts (PODVector<dContact>.)
+    void* contacts_;
     /// Collision infos to be sent as events.
     /// Collision infos to be sent as events.
     Vector<PhysicsCollisionInfo> collisionInfos_;
     Vector<PhysicsCollisionInfo> collisionInfos_;
     /// Cache for triangle mesh geometries.
     /// Cache for triangle mesh geometries.
     Map<String, SharedPtr<TriangleMeshData> > triangleMeshCache_;
     Map<String, SharedPtr<TriangleMeshData> > triangleMeshCache_;
     /// Cache for heightfield geometries.
     /// Cache for heightfield geometries.
     Map<String, SharedPtr<HeightfieldData> > heightfieldCache_;
     Map<String, SharedPtr<HeightfieldData> > heightfieldCache_;
+    /// Simulation steps per second.
+    unsigned fps_;
+    /// Maximum contacts per collision.
+    unsigned maxContacts_;
+    /// Simulation random seed.
+    unsigned randomSeed_;
+    /// Collision bounce velocity threshold.
+    float bounceThreshold_;
+    /// Maximum angular velocity for network replication.
+    float maxNetworkAngularVelocity_;
+    /// Simulation step time accumulator.
+    float timeAcc_;
+    /// Interpolation flag.
+    bool interpolation_;
 };
 };
 
 
 /// Register Physics library objects.
 /// Register Physics library objects.

+ 13 - 5
Engine/Physics/RigidBody.cpp

@@ -102,13 +102,19 @@ void RigidBody::SetMassAxis(int massAxis)
 void RigidBody::SetPosition(const Vector3& position)
 void RigidBody::SetPosition(const Vector3& position)
 {
 {
     if (body_)
     if (body_)
+    {
         dBodySetPosition(body_, position.x_, position.y_, position.z_);
         dBodySetPosition(body_, position.x_, position.y_, position.z_);
+        previousPosition_ = position;
+    }
 }
 }
 
 
 void RigidBody::SetRotation(const Quaternion& rotation)
 void RigidBody::SetRotation(const Quaternion& rotation)
 {
 {
     if (body_)
     if (body_)
+    {
         dBodySetQuaternion(body_, rotation.Data());
         dBodySetQuaternion(body_, rotation.Data());
+        previousRotation_ = rotation;
+    }
 }
 }
 
 
 void RigidBody::SetTransform(const Vector3& position, const Quaternion& rotation)
 void RigidBody::SetTransform(const Vector3& position, const Quaternion& rotation)
@@ -117,6 +123,8 @@ void RigidBody::SetTransform(const Vector3& position, const Quaternion& rotation
     {
     {
         dBodySetPosition(body_, position.x_, position.y_, position.z_);
         dBodySetPosition(body_, position.x_, position.y_, position.z_);
         dBodySetQuaternion(body_, rotation.Data());
         dBodySetQuaternion(body_, rotation.Data());
+        previousPosition_ = position;
+        previousRotation_ = rotation;
     }
     }
 }
 }
 
 
@@ -352,7 +360,7 @@ void RigidBody::OnMarkedDirty(Node* node)
     }
     }
     
     
     // If the node is smoothed, do not use the dirty callback, but rather update manually during prestep
     // If the node is smoothed, do not use the dirty callback, but rather update manually during prestep
-    if (node_->IsSmoothed())
+    if (node_->GetSmoothing())
         return;
         return;
     
     
     // Clear the dirty flag by querying world position; this way we are sure to get the dirty notification immediately
     // Clear the dirty flag by querying world position; this way we are sure to get the dirty notification immediately
@@ -407,7 +415,7 @@ void RigidBody::PreStep()
     const Vector3& currentPosition = *reinterpret_cast<const Vector3*>(dBodyGetPosition(body_));
     const Vector3& currentPosition = *reinterpret_cast<const Vector3*>(dBodyGetPosition(body_));
     const Quaternion& currentRotation = *reinterpret_cast<const Quaternion*>(dBodyGetQuaternion(body_));
     const Quaternion& currentRotation = *reinterpret_cast<const Quaternion*>(dBodyGetQuaternion(body_));
     
     
-    if (!node_->IsSmoothed())
+    if (!node_->GetSmoothing())
     {
     {
         // If no smoothing, store the current body position for interpolation
         // If no smoothing, store the current body position for interpolation
         previousPosition_ = currentPosition;
         previousPosition_ = currentPosition;
@@ -458,7 +466,7 @@ void RigidBody::PostStep(float t, HashSet<RigidBody*>& processedBodies)
     if (!parent)
     if (!parent)
     {
     {
         // If node already has motion smoothing enabled, do not do substep interpolation
         // If node already has motion smoothing enabled, do not do substep interpolation
-        if (!node_->IsSmoothed())
+        if (!node_->GetSmoothing())
             node_->SetTransform(previousPosition_.Lerp(currentPosition, t), previousRotation_.Slerp(currentRotation, t));
             node_->SetTransform(previousPosition_.Lerp(currentPosition, t), previousRotation_.Slerp(currentRotation, t));
         else
         else
             node_->SetTransform(currentPosition, currentRotation);
             node_->SetTransform(currentPosition, currentRotation);
@@ -466,7 +474,7 @@ void RigidBody::PostStep(float t, HashSet<RigidBody*>& processedBodies)
     else
     else
     {
     {
         // Transform rigid body's world coordinates back to parent's space
         // Transform rigid body's world coordinates back to parent's space
-        if (!node_->IsSmoothed())
+        if (!node_->GetSmoothing())
         {
         {
             Matrix3x4 newTransform(parent->GetWorldTransform().Inverse() * Matrix3x4(previousPosition_.Lerp(currentPosition, t),
             Matrix3x4 newTransform(parent->GetWorldTransform().Inverse() * Matrix3x4(previousPosition_.Lerp(currentPosition, t),
                 previousRotation_.Slerp(currentRotation, t), Vector3::ONE));
                 previousRotation_.Slerp(currentRotation, t), Vector3::ONE));
@@ -501,7 +509,7 @@ void RigidBody::CreateBody()
         // Set the user data pointer
         // Set the user data pointer
         dBodySetData(body_, this);
         dBodySetData(body_, this);
         
         
-        // Set initial transform. Use target position in case the node is smoothed
+        // Set initial transform. Use target position in case the node used smoothing
         const Vector3& position = node_->GetTargetPosition();
         const Vector3& position = node_->GetTargetPosition();
         Quaternion rotation(node_->GetTargetRotation());
         Quaternion rotation(node_->GetTargetRotation());
         dBodySetPosition(body_, position.x_, position.y_, position.z_);
         dBodySetPosition(body_, position.x_, position.y_, position.z_);

+ 14 - 14
Engine/Scene/Node.cpp

@@ -52,7 +52,7 @@ Node::Node(Context* context) :
     rotateCount_(0),
     rotateCount_(0),
     smoothingMask_(SMOOTH_NONE),
     smoothingMask_(SMOOTH_NONE),
     dirty_(false),
     dirty_(false),
-    smoothed_(false)
+    smoothing_(false)
 {
 {
 }
 }
 
 
@@ -229,7 +229,7 @@ void Node::SetName(const String& name)
 
 
 void Node::SetPosition(const Vector3& position)
 void Node::SetPosition(const Vector3& position)
 {
 {
-    if (!smoothed_)
+    if (!smoothing_)
     {
     {
         position_ = position;
         position_ = position;
         if (!dirty_)
         if (!dirty_)
@@ -244,7 +244,7 @@ void Node::SetPosition(const Vector3& position)
 
 
 void Node::SetRotation(const Quaternion& rotation)
 void Node::SetRotation(const Quaternion& rotation)
 {
 {
-    if (!smoothed_)
+    if (!smoothing_)
     {
     {
         rotation_ = rotation;
         rotation_ = rotation;
         if (!dirty_)
         if (!dirty_)
@@ -279,7 +279,7 @@ void Node::SetScale(const Vector3& scale)
 
 
 void Node::SetTransform(const Vector3& position, const Quaternion& rotation)
 void Node::SetTransform(const Vector3& position, const Quaternion& rotation)
 {
 {
-    if (!smoothed_)
+    if (!smoothing_)
     {
     {
         position_ = position;
         position_ = position;
         rotation_ = rotation;
         rotation_ = rotation;
@@ -297,7 +297,7 @@ void Node::SetTransform(const Vector3& position, const Quaternion& rotation)
 
 
 void Node::SetTransform(const Vector3& position, const Quaternion& rotation, float scale)
 void Node::SetTransform(const Vector3& position, const Quaternion& rotation, float scale)
 {
 {
-    if (!smoothed_)
+    if (!smoothing_)
     {
     {
         position_ = position;
         position_ = position;
         rotation_ = rotation;
         rotation_ = rotation;
@@ -316,7 +316,7 @@ void Node::SetTransform(const Vector3& position, const Quaternion& rotation, flo
 
 
 void Node::SetTransform(const Vector3& position, const Quaternion& rotation, const Vector3& scale)
 void Node::SetTransform(const Vector3& position, const Quaternion& rotation, const Vector3& scale)
 {
 {
-    if (!smoothed_)
+    if (!smoothing_)
     {
     {
         position_ = position;
         position_ = position;
         rotation_ = rotation;
         rotation_ = rotation;
@@ -436,7 +436,7 @@ void Node::SnapWorldRotation(const Quaternion& rotation)
 
 
 void Node::Translate(const Vector3& delta)
 void Node::Translate(const Vector3& delta)
 {
 {
-    if (!smoothed_)
+    if (!smoothing_)
     {
     {
         position_ += delta;
         position_ += delta;
         if (!dirty_)
         if (!dirty_)
@@ -451,7 +451,7 @@ void Node::Translate(const Vector3& delta)
 
 
 void Node::TranslateRelative(const Vector3& delta)
 void Node::TranslateRelative(const Vector3& delta)
 {
 {
-    if (!smoothed_)
+    if (!smoothing_)
     {
     {
         position_ += rotation_ * delta;
         position_ += rotation_ * delta;
         if (!dirty_)
         if (!dirty_)
@@ -466,7 +466,7 @@ void Node::TranslateRelative(const Vector3& delta)
 
 
 void Node::Rotate(const Quaternion& delta, bool fixedAxis)
 void Node::Rotate(const Quaternion& delta, bool fixedAxis)
 {
 {
-    if (!smoothed_)
+    if (!smoothing_)
     {
     {
         if (!fixedAxis)
         if (!fixedAxis)
             rotation_ = rotation_ * delta;
             rotation_ = rotation_ * delta;
@@ -485,7 +485,7 @@ void Node::Rotate(const Quaternion& delta, bool fixedAxis)
     ++rotateCount_;
     ++rotateCount_;
     if (rotateCount_ >= NORMALIZE_ROTATION_EVERY)
     if (rotateCount_ >= NORMALIZE_ROTATION_EVERY)
     {
     {
-        if (!smoothed_)
+        if (!smoothing_)
             rotation_.Normalize();
             rotation_.Normalize();
         else
         else
             targetRotation_.Normalize();
             targetRotation_.Normalize();
@@ -547,9 +547,9 @@ void Node::SetOwner(Connection* owner)
     owner_ = owner;
     owner_ = owner;
 }
 }
 
 
-void Node::SetSmoothed(bool enable)
+void Node::SetSmoothing(bool enable)
 {
 {
-    smoothed_ = enable;
+    smoothing_ = enable;
 }
 }
 
 
 void Node::MarkDirty()
 void Node::MarkDirty()
@@ -749,7 +749,7 @@ void Node::RemoveListener(Component* component)
 
 
 Matrix3x4 Node::GetWorldTargetTransform() const
 Matrix3x4 Node::GetWorldTargetTransform() const
 {
 {
-    if (!smoothed_)
+    if (!smoothing_)
         return GetWorldTransform();
         return GetWorldTransform();
     
     
     Matrix3x4 ret(targetPosition_, targetRotation_, scale_);
     Matrix3x4 ret(targetPosition_, targetRotation_, scale_);
@@ -1001,7 +1001,7 @@ const PODVector<unsigned char>& Node::GetNetParentAttr() const
 
 
 void Node::UpdateSmoothing(float constant, float squaredSnapThreshold)
 void Node::UpdateSmoothing(float constant, float squaredSnapThreshold)
 {
 {
-    if (!smoothed_ || !smoothingMask_)
+    if (!smoothing_ || !smoothingMask_)
         return;
         return;
     
     
     if (smoothingMask_ & SMOOTH_POSITION)
     if (smoothingMask_ & SMOOTH_POSITION)

+ 8 - 8
Engine/Scene/Node.h

@@ -139,7 +139,7 @@ public:
     /// %Set owner connection for networking.
     /// %Set owner connection for networking.
     void SetOwner(Connection* owner);
     void SetOwner(Connection* owner);
     /// Enable or disable motion smoothing.
     /// Enable or disable motion smoothing.
-    void SetSmoothed(bool enable);
+    void SetSmoothing(bool enable);
     /// Mark node and child nodes to need world transform recalculation. Notify listener components.
     /// Mark node and child nodes to need world transform recalculation. Notify listener components.
     void MarkDirty();
     void MarkDirty();
     /// Create a child scene node.
     /// Create a child scene node.
@@ -194,9 +194,9 @@ public:
     /// Return scale.
     /// Return scale.
     const Vector3& GetScale() const { return scale_; }
     const Vector3& GetScale() const { return scale_; }
     /// Return unsmoothed (target) position.
     /// Return unsmoothed (target) position.
-    const Vector3& GetTargetPosition() const { return smoothed_ ? targetPosition_ : position_; }
+    const Vector3& GetTargetPosition() const { return smoothing_ ? targetPosition_ : position_; }
     /// Return unsmoothed (target) rotation.
     /// Return unsmoothed (target) rotation.
-    const Quaternion& GetTargetRotation() const { return smoothed_ ? targetRotation_ : rotation_; }
+    const Quaternion& GetTargetRotation() const { return smoothing_ ? targetRotation_ : rotation_; }
     /// Return local transform.
     /// Return local transform.
     Matrix3x4 GetTransform() const { return Matrix3x4(position_, rotation_, scale_); }
     Matrix3x4 GetTransform() const { return Matrix3x4(position_, rotation_, scale_); }
     /// Return unsmoothed (target) local transform.
     /// Return unsmoothed (target) local transform.
@@ -239,9 +239,9 @@ public:
     }
     }
     
     
     /// Return world-space unsmoothed (target) position. Is recalculated each time.
     /// Return world-space unsmoothed (target) position. Is recalculated each time.
-    Vector3 GetWorldTargetPosition() const { return smoothed_ ? GetWorldTargetTransform().Translation() : GetWorldPosition(); }
+    Vector3 GetWorldTargetPosition() const { return smoothing_ ? GetWorldTargetTransform().Translation() : GetWorldPosition(); }
     /// Return world-space unsmoothed (target) rotation. Is recalculated each time.
     /// Return world-space unsmoothed (target) rotation. Is recalculated each time.
-    Quaternion GetWorldTargetRotation() const { return smoothed_ ? GetWorldTargetTransform().Rotation() : GetWorldRotation(); }
+    Quaternion GetWorldTargetRotation() const { return smoothing_ ? GetWorldTargetTransform().Rotation() : GetWorldRotation(); }
     
     
     /// Return world-space transform.
     /// Return world-space transform.
     const Matrix3x4& GetWorldTransform() const
     const Matrix3x4& GetWorldTransform() const
@@ -265,7 +265,7 @@ public:
     /// Return whether transform has changed and world transform needs recalculation.
     /// Return whether transform has changed and world transform needs recalculation.
     bool IsDirty() const { return dirty_; }
     bool IsDirty() const { return dirty_; }
     /// Return whether motion smoothing is enabled.
     /// Return whether motion smoothing is enabled.
-    bool IsSmoothed() const { return smoothed_; }
+    bool GetSmoothing() const { return smoothing_; }
     /// Return number of child scene nodes.
     /// Return number of child scene nodes.
     unsigned GetNumChildren(bool recursive = false) const;
     unsigned GetNumChildren(bool recursive = false) const;
     /// Return immediate child scene nodes.
     /// Return immediate child scene nodes.
@@ -387,8 +387,8 @@ private:
     unsigned char smoothingMask_;
     unsigned char smoothingMask_;
     /// World transform needs update flag.
     /// World transform needs update flag.
     mutable bool dirty_;
     mutable bool dirty_;
-    /// Smoothed motion flag.
-    bool smoothed_;
+    /// Smoothing motion flag.
+    bool smoothing_;
 };
 };
 
 
 template <class T> T* Node::CreateComponent(CreateMode mode) { return static_cast<T*>(CreateComponent(T::GetTypeStatic(), mode)); }
 template <class T> T* Node::CreateComponent(CreateMode mode) { return static_cast<T*>(CreateComponent(T::GetTypeStatic(), mode)); }

+ 1 - 1
Engine/Scene/Scene.cpp

@@ -455,7 +455,7 @@ void Scene::Update(float timeStep)
     SendEvent(E_SCENESUBSYSTEMUPDATE, eventData);
     SendEvent(E_SCENESUBSYSTEMUPDATE, eventData);
     
     
     // Update smoothing if enabled (network client scenes)
     // Update smoothing if enabled (network client scenes)
-    if (IsSmoothed())
+    if (GetSmoothing())
     {
     {
         PROFILE(UpdateSmoothing);
         PROFILE(UpdateSmoothing);