From b1d0fab954545e1ed9aa13c0c760b3371042c437 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 26 Aug 2012 20:33:45 +0100 Subject: fix incoerence btw KFM_TRANSLATION and ROTATION LSL constants and internal DataFormat enum, using values from the KFM constants --- OpenSim/Region/Framework/Scenes/KeyframeMotion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes') diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index b7b0d27..6ee09b7 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs @@ -38,8 +38,8 @@ namespace OpenSim.Region.Framework.Scenes [Flags] public enum DataFormat : int { - Translation = 1, - Rotation = 2 + Translation = 2, + Rotation = 1 } [Serializable] -- cgit v1.1 From ef6e007a4c7301dbd7a1a0392a07664e7034201b Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Tue, 28 Aug 2012 03:21:03 +0100 Subject: [possible still very broken] mess around keyframes. timer events threads overlaps, some null objects exceptions, region crossing... --- OpenSim/Region/Framework/Scenes/KeyframeMotion.cs | 368 +++++++++++++++------ OpenSim/Region/Framework/Scenes/Scene.cs | 6 + .../Region/Framework/Scenes/SceneObjectGroup.cs | 29 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 5 +- .../Scenes/Serialization/SceneObjectSerializer.cs | 2 +- 5 files changed, 299 insertions(+), 111 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes') diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index 6ee09b7..4e6425f 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs @@ -58,12 +58,31 @@ namespace OpenSim.Region.Framework.Scenes private Vector3 m_serializedPosition; private Keyframe m_currentFrame; + private List m_frames = new List(); private Keyframe[] m_keyframes; [NonSerialized()] - protected Timer m_timer = new Timer(); + protected Timer m_timer = null; + + // timer lock + [NonSerialized()] + private object m_onTimerLock; + + // timer overrun detect + // prevents overlap or timer events threads frozen on the lock + [NonSerialized()] + private bool m_inOnTimer; + + // skip timer events. + //timer.stop doesn't assure there aren't event threads still being fired + [NonSerialized()] + private bool m_skipOnTimer; + + // retry position for cross fail + [NonSerialized()] + private Vector3 m_nextPosition; [NonSerialized()] private SceneObjectGroup m_group; @@ -88,7 +107,7 @@ namespace OpenSim.Region.Framework.Scenes { set { - if (value) + if (!value) { // Once we're let go, recompute positions if (m_selected) @@ -100,7 +119,8 @@ namespace OpenSim.Region.Framework.Scenes if (!m_selected) m_serializedPosition = m_group.AbsolutePosition; } - m_selected = value; } + m_selected = value; + } } public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) @@ -111,31 +131,65 @@ namespace OpenSim.Region.Framework.Scenes KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms); +/* + * create timer in start() + * this was creating unneeded timers + // This will be started when position is updated + newMotion.m_timer = new Timer(); newMotion.m_timer.Interval = (int)timerInterval; newMotion.m_timer.AutoReset = true; newMotion.m_timer.Elapsed += newMotion.OnTimer; +*/ + newMotion.m_group = grp; + if (grp != null && grp.IsSelected) + newMotion.m_selected = true; + + newMotion.m_onTimerLock = new object(); + newMotion.m_skipOnTimer = false; + newMotion.m_inOnTimer = false; return newMotion; } public void UpdateSceneObject(SceneObjectGroup grp) { - m_group = grp; - Vector3 offset = grp.AbsolutePosition - m_serializedPosition; - - m_basePosition += offset; - m_currentFrame.Position += offset; - for (int i = 0 ; i < m_frames.Count ; i++) +// lock (m_onTimerLock) { - Keyframe k = m_frames[i]; - k.Position += offset; - m_frames[i] = k; - } + m_skipOnTimer = true; + if (m_timer != null) + m_timer.Stop(); + + m_group = grp; + Vector3 grppos = grp.AbsolutePosition; + Vector3 offset = grppos - m_serializedPosition; + // avoid doing it more than once + // current this will happen draging a prim to other region + m_serializedPosition = grppos; + + m_basePosition += offset; + m_currentFrame.Position += offset; + + m_nextPosition += offset; +/* + for (int i = 0; i < m_frames.Count; i++) + { + Keyframe k = m_frames[i]; + k.Position += offset; + m_frames[i] = k; + } +*/ + for (int i = 0; i < m_frames.Count; i++) + { + Keyframe k = m_frames[i]; + k.Position += offset; + m_frames[i]=k; + } - if (m_running) - Start(); + if (m_running) + Start(); + } } public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data) @@ -143,13 +197,16 @@ namespace OpenSim.Region.Framework.Scenes m_mode = mode; m_data = data; + m_onTimerLock = new object(); + m_group = grp; m_basePosition = grp.AbsolutePosition; m_baseRotation = grp.GroupRotation; - +/* m_timer.Interval = (int)timerInterval; m_timer.AutoReset = true; m_timer.Elapsed += OnTimer; + */ } public void SetKeyframes(Keyframe[] frames) @@ -157,19 +214,63 @@ namespace OpenSim.Region.Framework.Scenes m_keyframes = frames; } + public void Delete() + { + m_skipOnTimer = true; + m_frames.Clear(); + m_keyframes = null; + m_running = false; + + if (m_timer == null) + return; + + m_timer.Stop(); + m_timer.Elapsed -= OnTimer; + m_timer = null; + } + public void Start() { if (m_keyframes.Length > 0) + { + if (m_timer == null) + { + m_timer = new Timer(); + m_timer.Interval = (int)timerInterval; + m_timer.AutoReset = true; + m_timer.Elapsed += OnTimer; + } + + m_skipOnTimer = false; + m_inOnTimer = false; + m_timer.Start(); - m_running = true; + m_running = true; + } + else + { + m_running = false; + m_skipOnTimer = true; + if (m_timer != null) + { + m_timer.Stop(); + m_timer.Elapsed -= OnTimer; + m_timer = null; + } + } } public void Stop() { + m_skipOnTimer = true; + // Failed object creation if (m_timer == null) return; + m_timer.Stop(); + m_timer.Elapsed -= OnTimer; + m_timer = null; m_basePosition = m_group.AbsolutePosition; m_baseRotation = m_group.GroupRotation; @@ -184,6 +285,8 @@ namespace OpenSim.Region.Framework.Scenes public void Pause() { + m_skipOnTimer = true; + m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); m_group.SendGroupRootTerseUpdate(); @@ -284,138 +387,197 @@ namespace OpenSim.Region.Framework.Scenes protected void OnTimer(object sender, ElapsedEventArgs e) { - if (m_frames.Count == 0) - { - GetNextList(); - - if (m_frames.Count == 0) - { - Stop(); - return; - } - - m_currentFrame = m_frames[0]; - } - - if (m_selected) + if (m_inOnTimer) { - if (m_group.RootPart.Velocity != Vector3.Zero) - { - m_group.RootPart.Velocity = Vector3.Zero; - m_group.SendGroupRootTerseUpdate(); - } + m_log.Error("[KeyFrame]: timer overrun"); return; } - // Do the frame processing - double steps = (double)m_currentFrame.TimeMS / timerInterval; - float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; - - if (steps <= 1.0) +// lock (m_onTimerLock) { - m_currentFrame.TimeMS = 0; - - m_group.AbsolutePosition = (Vector3)m_currentFrame.Position; - m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); - } - else - { - Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition; - Vector3 motionThisFrame = v / (float)steps; - v = v * 1000 / m_currentFrame.TimeMS; - - bool update = false; + if (m_skipOnTimer) + return; - if (Vector3.Mag(motionThisFrame) >= 0.05f) + m_inOnTimer = true; + try { - m_group.AbsolutePosition += motionThisFrame; - m_group.RootPart.Velocity = v; - update = true; - } + if (m_frames.Count == 0) + { + GetNextList(); - if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) - { - Quaternion current = m_group.GroupRotation; + if (m_frames.Count == 0) + { + Stop(); + m_inOnTimer = false; + return; + } - Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); + m_currentFrame = m_frames[0]; + } - float angle = 0; + if (m_selected) + { + if (m_group.RootPart.Velocity != Vector3.Zero) + { + m_group.RootPart.Velocity = Vector3.Zero; + m_group.SendGroupRootTerseUpdate(); + } + m_inOnTimer = false; + return; + } - float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; - float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; - float aa_bb = aa * bb; + // Do the frame processing + double steps = (double)m_currentFrame.TimeMS / timerInterval; + float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; - if (aa_bb == 0) + if (steps <= 1.0) { - angle = 0; + m_currentFrame.TimeMS = 0; + + // m_group.AbsolutePosition = (Vector3)m_currentFrame.Position; + m_nextPosition = (Vector3)m_currentFrame.Position; + m_group.AbsolutePosition = m_nextPosition; + + m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); } else { - float ab = current.X * step.X + - current.Y * step.Y + - current.Z * step.Z + - current.W * step.W; - float q = (ab * ab) / aa_bb; + Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition; + Vector3 motionThisFrame = v / (float)steps; + v = v * 1000 / m_currentFrame.TimeMS; - if (q > 1.0f) + bool update = false; + + if (Vector3.Mag(motionThisFrame) >= 0.05f) { - angle = 0; + // m_group.AbsolutePosition += motionThisFrame; + m_nextPosition = m_group.AbsolutePosition + motionThisFrame; + m_group.AbsolutePosition = m_nextPosition; + + m_group.RootPart.Velocity = v; + update = true; } - else + + if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) { - angle = (float)Math.Acos(2 * q - 1); + Quaternion current = m_group.GroupRotation; + + Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); + + float angle = 0; + + float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; + float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; + float aa_bb = aa * bb; + + if (aa_bb == 0) + { + angle = 0; + } + else + { + float ab = current.X * step.X + + current.Y * step.Y + + current.Z * step.Z + + current.W * step.W; + float q = (ab * ab) / aa_bb; + + if (q > 1.0f) + { + angle = 0; + } + else + { + angle = (float)Math.Acos(2 * q - 1); + } + } + + if (angle > 0.01f) + { + m_group.UpdateGroupRotationR(step); + //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); + update = true; + } } + + if (update) + m_group.SendGroupRootTerseUpdate(); } - if (angle > 0.01f) + m_currentFrame.TimeMS -= (int)timerInterval; + + if (m_currentFrame.TimeMS <= 0) { - m_group.UpdateGroupRotationR(step); - //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); - update = true; + m_group.RootPart.Velocity = Vector3.Zero; + m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); + m_group.SendGroupRootTerseUpdate(); + + m_frames.RemoveAt(0); + if (m_frames.Count > 0) + m_currentFrame = m_frames[0]; } } - - if (update) - m_group.SendGroupRootTerseUpdate(); + finally + { + m_inOnTimer = false; + } } + } - m_currentFrame.TimeMS -= (int)timerInterval; - - if (m_currentFrame.TimeMS <= 0) + public Byte[] Serialize(bool StopMoveTimer) + { + MemoryStream ms = new MemoryStream(); + if (StopMoveTimer && m_timer != null) { - m_group.RootPart.Velocity = Vector3.Zero; - m_group.RootPart.UpdateAngularVelocity(Vector3.Zero); - m_group.SendGroupRootTerseUpdate(); + m_skipOnTimer = true; + m_timer.Stop(); + } - m_frames.RemoveAt(0); - if (m_frames.Count > 0) - m_currentFrame = m_frames[0]; +// lock (m_onTimerLock) + { + BinaryFormatter fmt = new BinaryFormatter(); + SceneObjectGroup tmp = m_group; + m_group = null; + if(!m_selected) + m_serializedPosition = tmp.AbsolutePosition; + fmt.Serialize(ms, this); + m_group = tmp; + return ms.ToArray(); } } - public Byte[] Serialize() + public void StartCrossingCheck() { - MemoryStream ms = new MemoryStream(); - m_timer.Stop(); + m_skipOnTimer = true; + if (m_timer != null) + m_timer.Stop(); - BinaryFormatter fmt = new BinaryFormatter(); - SceneObjectGroup tmp = m_group; - m_group = null; - m_serializedPosition = tmp.AbsolutePosition; - fmt.Serialize(ms, this); - m_group = tmp; - return ms.ToArray(); + if (m_group.RootPart.Velocity != Vector3.Zero) + { + m_group.RootPart.Velocity = Vector3.Zero; + m_group.SendGroupRootTerseUpdate(); + } } public void CrossingFailure() { // The serialization has stopped the timer, so let's wait a moment // then retry the crossing. We'll get back here if it fails. + // if it is a open border there is no serialization + // so make sure timer is actually stopped + + m_group.RootPart.Velocity = Vector3.Zero; + m_group.SendGroupRootTerseUpdate(); + Util.FireAndForget(delegate (object x) { Thread.Sleep(60000); if (m_running) + { + m_skipOnTimer = false; m_timer.Start(); + m_group.AbsolutePosition = m_nextPosition; + } }); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 57fcf51..0237021 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2346,6 +2346,12 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in partList) { + if (part.KeyframeMotion != null) + { + part.KeyframeMotion.Delete(); + part.KeyframeMotion = null; + } + if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) { PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index eee53d7..65a1da2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -509,6 +509,9 @@ namespace OpenSim.Region.Framework.Scenes Vector3 newpos = Vector3.Zero; OpenSim.Services.Interfaces.GridRegion destination = null; + if (m_rootPart.KeyframeMotion != null) + m_rootPart.KeyframeMotion.StartCrossingCheck(); + bool canCross = true; foreach (ScenePresence av in m_linkedAvatars) { @@ -551,7 +554,7 @@ namespace OpenSim.Region.Framework.Scenes av.ParentID = 0; } -// m_linkedAvatars.Clear(); + // m_linkedAvatars.Clear(); m_scene.CrossPrimGroupIntoNewRegion(val, this, true); // Normalize @@ -599,11 +602,16 @@ namespace OpenSim.Region.Framework.Scenes avsToCross.Clear(); } - else if (RootPart.PhysActor != null) + else { - RootPart.PhysActor.CrossingFailure(); - } + if (m_rootPart.KeyframeMotion != null) + m_rootPart.KeyframeMotion.CrossingFailure(); + if (RootPart.PhysActor != null) + { + RootPart.PhysActor.CrossingFailure(); + } + } Vector3 oldp = AbsolutePosition; val.X = Util.Clamp(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); val.Y = Util.Clamp(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); @@ -2058,8 +2066,8 @@ namespace OpenSim.Region.Framework.Scenes { if (part.KeyframeMotion != null) { - part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize()); - part.KeyframeMotion.UpdateSceneObject(this); + part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize(false)); +// part.KeyframeMotion.UpdateSceneObject(this); } }); @@ -4407,6 +4415,15 @@ namespace OpenSim.Region.Framework.Scenes public virtual ISceneObject CloneForNewScene() { SceneObjectGroup sog = Copy(false); + sog.ForEachPart(delegate(SceneObjectPart part) + { + if (part.KeyframeMotion != null) + { + part.KeyframeMotion = KeyframeMotion.FromData(sog, part.KeyframeMotion.Serialize(true)); + // this is called later +// part.KeyframeMotion.UpdateSceneObject(this); + } + }); sog.IsDeleted = false; return sog; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index ed626d0..bf5fc99 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -769,7 +769,7 @@ namespace OpenSim.Region.Framework.Scenes { m_groupPosition = value; PhysicsActor actor = PhysActor; - if (actor != null) + if (actor != null && ParentGroup.Scene.PhysicsScene != null) { try { @@ -3408,6 +3408,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendTerseUpdateToAllClients() { + if (ParentGroup == null || ParentGroup.Scene == null) + return; + ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) { SendTerseUpdateToClient(client); diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 134bd9d..1c75607 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -1241,7 +1241,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization if (sog.RootPart.KeyframeMotion != null) { - Byte[] data = sog.RootPart.KeyframeMotion.Serialize(); + Byte[] data = sog.RootPart.KeyframeMotion.Serialize(true); writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); writer.WriteBase64(data, 0, data.Length); -- cgit v1.1