private VelocityStatus CheckSyncVelocity(OpenMetaverse.Vector3 posDiff) { VelocityStatus status = VelocityStatus.NoChange; //check my angular and linear velocity OpenMetaverse.Vector3 newVel = PhysUtil.PhysxVectorToOmv(_dynActor.LinearVelocity); if (newVel != _velocity) { if (newVel == OpenMetaverse.Vector3.Zero) { // we need to assume there is no acceleration acting on the prim anymore // or our objects will float away instead of coming to rest in their final movement _acceleration = OpenMetaverse.Vector3.Zero; _velocity = OpenMetaverse.Vector3.Zero; _lastAccelVelUpdate = 0; status |= VelocityStatus.Zeroed; } else { //try to get a semi-accurate FPS to send the viewer the correct acceleration ulong tickCountNow = Util.GetLongTickCount(); ulong timeDiff = tickCountNow - _lastAccelVelUpdate; float fps; if (_lastAccelVelUpdate == 0 || timeDiff <= 0) { fps = NOMINAL_FPS; } else { fps = 1.0f / (timeDiff * 0.001f); } var lastAccel = _acceleration; var newAccel = (newVel - _velocity) * fps; _velocity = newVel; if (!lastAccel.ApproxEquals(newAccel, ACCEL_COMPARISON_TOLERANCE * _velocity.Length())) { //m_log.DebugFormat("Vel: {0} Accel: {1} Fps: {2}", _velocity, newAccel, fps); _acceleration = newAccel; status |= VelocityStatus.Changed; } _lastAccelVelUpdate = tickCountNow; } } else { if (_velocity != OpenMetaverse.Vector3.Zero) { _acceleration = OpenMetaverse.Vector3.Zero; _lastAccelVelUpdate = Util.GetLongTickCount(); status |= VelocityStatus.Changed; } } if (status != VelocityStatus.NoChange) { _angularVelocity = PhysUtil.PhysxVectorToOmv(_dynActor.AngularVelocity); } else { OpenMetaverse.Vector3 newAngVel = PhysUtil.PhysxVectorToOmv(_dynActor.AngularVelocity); //m_log.DebugFormat("AngVel: {0}, NewAngVel: {1}", _angularVelocity, newAngVel); if (newAngVel == OpenMetaverse.Vector3.Zero) { if (newAngVel != _angularVelocity) { _angularVelocity = OpenMetaverse.Vector3.Zero; status |= VelocityStatus.AngularChanged; } } else if (!newAngVel.ApproxEquals(_angularVelocity, ANGULAR_VELOCITY_COMPARISON_TOLERANCE * _angularVelocity.Length())) { //Console.Out.WriteLine("Ang: {0}", _angularVelocity); _angularVelocity = newAngVel; status |= VelocityStatus.AngularChanged; } else { //Angular velocity hasnt changed or zeroed. BUT if angular velocity is set and //the center of mass isnt at 0,0,0 and POS has changed we need to send an update if (!_centerOfMassNearlyZero && !posDiff.ApproxEquals(OpenMetaverse.Vector3.Zero, POS_ANGULAR_VEL_TOLERANCE)) { _angularVelocity = newAngVel; status |= VelocityStatus.AngularPosChanged; _useAngularVelocity = false; } else { if (_useAngularVelocity == false) { status |= VelocityStatus.AngularPosChanged; _useAngularVelocity = true; } } } } return status; }