aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs315
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs3
3 files changed, 330 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
new file mode 100644
index 0000000..239f7ca
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -0,0 +1,315 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker
3//
4
5using System;
6using System.Timers;
7using System.Collections.Generic;
8using System.IO;
9using System.Diagnostics;
10using System.Reflection;
11using System.Threading;
12using OpenMetaverse;
13using OpenSim.Framework;
14using OpenSim.Region.Framework.Interfaces;
15using OpenSim.Region.Physics.Manager;
16using OpenSim.Region.Framework.Scenes.Serialization;
17using Timer = System.Timers.Timer;
18using log4net;
19
20namespace OpenSim.Region.Framework.Scenes
21{
22 public class KeyframeMotion
23 {
24 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
25
26 public enum PlayMode : int
27 {
28 Forward = 0,
29 Reverse = 1,
30 Loop = 2,
31 PingPong = 3
32 };
33
34 [Flags]
35 public enum DataFormat : int
36 {
37 Translation = 1,
38 Rotation = 2
39 }
40
41 public struct Keyframe
42 {
43 public Vector3? Position;
44 public Quaternion? Rotation;
45 public Quaternion StartRotation;
46 public int TimeMS;
47 public int TimeTotal;
48 public Vector3 AngularVelocity;
49 };
50
51 private Vector3 m_basePosition;
52 private Quaternion m_baseRotation;
53
54 private Keyframe m_currentFrame;
55 private List<Keyframe> m_frames = new List<Keyframe>();
56
57 private Keyframe[] m_keyframes;
58
59 private Timer m_timer = new Timer();
60
61 private readonly SceneObjectGroup m_group;
62
63 private PlayMode m_mode = PlayMode.Forward;
64 private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation;
65
66 private int m_iterations = 0;
67
68 private const double timerInterval = 50.0;
69
70 public DataFormat Data
71 {
72 get { return m_data; }
73 }
74
75 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
76 {
77 m_mode = mode;
78 m_data = data;
79
80 m_group = grp;
81 m_basePosition = grp.AbsolutePosition;
82 m_baseRotation = grp.GroupRotation;
83
84 m_timer.Interval = (int)timerInterval;
85 m_timer.AutoReset = true;
86 m_timer.Elapsed += OnTimer;
87 }
88
89 public void SetKeyframes(Keyframe[] frames)
90 {
91 m_keyframes = frames;
92 }
93
94 public void Start()
95 {
96 if (m_keyframes.Length > 0)
97 m_timer.Start();
98 }
99
100 public void Stop()
101 {
102 m_timer.Stop();
103
104 m_basePosition = m_group.AbsolutePosition;
105 m_baseRotation = m_group.GroupRotation;
106
107 m_group.RootPart.Velocity = Vector3.Zero;
108 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
109 m_group.SendGroupRootTerseUpdate();
110
111 m_frames.Clear();
112 }
113
114 public void Pause()
115 {
116 m_group.RootPart.Velocity = Vector3.Zero;
117 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
118 m_group.SendGroupRootTerseUpdate();
119
120 m_timer.Stop();
121 }
122
123 private void GetNextList()
124 {
125 m_frames.Clear();
126 Vector3 pos = m_basePosition;
127 Quaternion rot = m_baseRotation;
128
129 if (m_mode == PlayMode.Loop || m_mode == PlayMode.PingPong || m_iterations == 0)
130 {
131 int direction = 1;
132 if (m_mode == PlayMode.Reverse || ((m_mode == PlayMode.PingPong) && ((m_iterations & 1) != 0)))
133 direction = -1;
134
135 int start = 0;
136 int end = m_keyframes.Length;
137// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
138// end = m_keyframes.Length - 1;
139
140 if (direction < 0)
141 {
142 start = m_keyframes.Length - 1;
143 end = -1;
144// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
145// end = 0;
146 }
147
148 for (int i = start; i != end ; i += direction)
149 {
150 Keyframe k = m_keyframes[i];
151
152 if (k.Position.HasValue)
153 k.Position = (k.Position * direction) + pos;
154 else
155 k.Position = pos;
156
157 k.StartRotation = rot;
158 if (k.Rotation.HasValue)
159 {
160 if (direction == -1)
161 k.Rotation = Quaternion.Conjugate((Quaternion)k.Rotation);
162 k.Rotation = rot * k.Rotation;
163 }
164 else
165 {
166 k.Rotation = rot;
167 }
168
169 float angle = 0;
170
171 float aa = k.StartRotation.X * k.StartRotation.X + k.StartRotation.Y * k.StartRotation.Y + k.StartRotation.Z * k.StartRotation.Z + k.StartRotation.W * k.StartRotation.W;
172 float bb = ((Quaternion)k.Rotation).X * ((Quaternion)k.Rotation).X + ((Quaternion)k.Rotation).Y * ((Quaternion)k.Rotation).Y + ((Quaternion)k.Rotation).Z * ((Quaternion)k.Rotation).Z + ((Quaternion)k.Rotation).W * ((Quaternion)k.Rotation).W;
173 float aa_bb = aa * bb;
174
175 if (aa_bb == 0)
176 {
177 angle = 0;
178 }
179 else
180 {
181 float ab = k.StartRotation.X * ((Quaternion)k.Rotation).X +
182 k.StartRotation.Y * ((Quaternion)k.Rotation).Y +
183 k.StartRotation.Z * ((Quaternion)k.Rotation).Z +
184 k.StartRotation.W * ((Quaternion)k.Rotation).W;
185 float q = (ab * ab) / aa_bb;
186
187 if (q > 1.0f)
188 {
189 angle = 0;
190 }
191 else
192 {
193 angle = (float)Math.Acos(2 * q - 1);
194 }
195 }
196
197 m_log.DebugFormat("[KEYFRAME]: Angle {0} aabb {1}", angle, aa_bb);
198 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000));
199 k.TimeTotal = k.TimeMS;
200
201 m_frames.Add(k);
202
203 pos = (Vector3)k.Position;
204 rot = (Quaternion)k.Rotation;
205 }
206
207 m_basePosition = pos;
208 m_baseRotation = rot;
209
210 m_iterations++;
211 }
212 }
213
214 private void OnTimer(object sender, ElapsedEventArgs e)
215 {
216 if (m_frames.Count == 0)
217 {
218 GetNextList();
219
220 if (m_frames.Count == 0)
221 {
222 Stop();
223 return;
224 }
225
226 m_currentFrame = m_frames[0];
227 }
228
229 // Do the frame processing
230 double steps = (double)m_currentFrame.TimeMS / timerInterval;
231 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
232
233 if (steps <= 1.0)
234 {
235 m_currentFrame.TimeMS = 0;
236
237 m_group.AbsolutePosition = (Vector3)m_currentFrame.Position;
238 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
239 }
240 else
241 {
242 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
243 Vector3 motionThisFrame = v / (float)steps;
244 v = v * 1000 / m_currentFrame.TimeMS;
245
246 bool update = false;
247
248 if (Vector3.Mag(motionThisFrame) >= 0.05f)
249 {
250 m_group.AbsolutePosition += motionThisFrame;
251 m_group.RootPart.Velocity = v;
252 update = true;
253 }
254
255 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
256 {
257 Quaternion current = m_group.GroupRotation;
258
259 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
260
261 float angle = 0;
262
263 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
264 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
265 float aa_bb = aa * bb;
266
267 if (aa_bb == 0)
268 {
269 angle = 0;
270 }
271 else
272 {
273 float ab = current.X * step.X +
274 current.Y * step.Y +
275 current.Z * step.Z +
276 current.W * step.W;
277 float q = (ab * ab) / aa_bb;
278
279 if (q > 1.0f)
280 {
281 angle = 0;
282 }
283 else
284 {
285 angle = (float)Math.Acos(2 * q - 1);
286 }
287 }
288
289 if (angle > 0.01f)
290 {
291 m_group.UpdateGroupRotationR(step);
292 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
293 update = true;
294 }
295 }
296
297 if (update)
298 m_group.SendGroupRootTerseUpdate();
299 }
300
301 m_currentFrame.TimeMS -= (int)timerInterval;
302
303 if (m_currentFrame.TimeMS <= 0)
304 {
305 m_group.RootPart.Velocity = Vector3.Zero;
306 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
307 m_group.SendGroupRootTerseUpdate();
308
309 m_frames.RemoveAt(0);
310 if (m_frames.Count > 0)
311 m_currentFrame = m_frames[0];
312 }
313 }
314 }
315}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e9021f1..9898681 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -114,6 +114,12 @@ namespace OpenSim.Region.Framework.Scenes
114 private Random m_rand; 114 private Random m_rand;
115 private bool m_suspendUpdates; 115 private bool m_suspendUpdates;
116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>(); 116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
117 private KeyframeMotion m_keyframeMotion = null;
118
119 public KeyframeMotion KeyframeMotion
120 {
121 get; set;
122 }
117 123
118 public bool areUpdatesSuspended 124 public bool areUpdatesSuspended
119 { 125 {
@@ -1982,6 +1988,12 @@ namespace OpenSim.Region.Framework.Scenes
1982 1988
1983 public void ScriptSetPhysicsStatus(bool usePhysics) 1989 public void ScriptSetPhysicsStatus(bool usePhysics)
1984 { 1990 {
1991 if (usePhysics)
1992 {
1993 if (KeyframeMotion != null)
1994 KeyframeMotion.Stop();
1995 KeyframeMotion = null;
1996 }
1985 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 1997 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1986 } 1998 }
1987 1999
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index f35a27e..825f2a3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1921,6 +1921,9 @@ namespace OpenSim.Region.Framework.Scenes
1921 { 1921 {
1922 if (UsePhysics) 1922 if (UsePhysics)
1923 { 1923 {
1924 if (ParentGroup.KeyframeMotion != null)
1925 ParentGroup.KeyframeMotion.Stop();
1926 ParentGroup.KeyframeMotion = null;
1924 ParentGroup.Scene.AddPhysicalPrim(1); 1927 ParentGroup.Scene.AddPhysicalPrim(1);
1925 1928
1926 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 1929 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;