diff options
Merge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/KeyframeMotion.cs | 513 |
1 files changed, 286 insertions, 227 deletions
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index 5cfba39..b102e48 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs | |||
@@ -22,6 +22,115 @@ using log4net; | |||
22 | 22 | ||
23 | namespace OpenSim.Region.Framework.Scenes | 23 | namespace OpenSim.Region.Framework.Scenes |
24 | { | 24 | { |
25 | public class KeyframeTimer | ||
26 | { | ||
27 | private static Dictionary<Scene, KeyframeTimer>m_timers = | ||
28 | new Dictionary<Scene, KeyframeTimer>(); | ||
29 | |||
30 | private Timer m_timer; | ||
31 | private Dictionary<KeyframeMotion, object> m_motions = new Dictionary<KeyframeMotion, object>(); | ||
32 | private object m_lockObject = new object(); | ||
33 | private object m_timerLock = new object(); | ||
34 | private const double m_tickDuration = 50.0; | ||
35 | private Scene m_scene; | ||
36 | |||
37 | public double TickDuration | ||
38 | { | ||
39 | get { return m_tickDuration; } | ||
40 | } | ||
41 | |||
42 | public KeyframeTimer(Scene scene) | ||
43 | { | ||
44 | m_timer = new Timer(); | ||
45 | m_timer.Interval = TickDuration; | ||
46 | m_timer.AutoReset = true; | ||
47 | m_timer.Elapsed += OnTimer; | ||
48 | |||
49 | m_scene = scene; | ||
50 | |||
51 | m_timer.Start(); | ||
52 | } | ||
53 | |||
54 | private void OnTimer(object sender, ElapsedEventArgs ea) | ||
55 | { | ||
56 | if (!Monitor.TryEnter(m_timerLock)) | ||
57 | return; | ||
58 | |||
59 | try | ||
60 | { | ||
61 | List<KeyframeMotion> motions; | ||
62 | |||
63 | lock (m_lockObject) | ||
64 | { | ||
65 | motions = new List<KeyframeMotion>(m_motions.Keys); | ||
66 | } | ||
67 | |||
68 | foreach (KeyframeMotion m in motions) | ||
69 | { | ||
70 | try | ||
71 | { | ||
72 | m.OnTimer(TickDuration); | ||
73 | } | ||
74 | catch (Exception inner) | ||
75 | { | ||
76 | // Don't stop processing | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | catch (Exception e) | ||
81 | { | ||
82 | // Keep running no matter what | ||
83 | } | ||
84 | finally | ||
85 | { | ||
86 | Monitor.Exit(m_timerLock); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | public static void Add(KeyframeMotion motion) | ||
91 | { | ||
92 | KeyframeTimer timer; | ||
93 | |||
94 | if (motion.Scene == null) | ||
95 | return; | ||
96 | |||
97 | lock (m_timers) | ||
98 | { | ||
99 | if (!m_timers.TryGetValue(motion.Scene, out timer)) | ||
100 | { | ||
101 | timer = new KeyframeTimer(motion.Scene); | ||
102 | m_timers[motion.Scene] = timer; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | lock (timer.m_lockObject) | ||
107 | { | ||
108 | timer.m_motions[motion] = null; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | public static void Remove(KeyframeMotion motion) | ||
113 | { | ||
114 | KeyframeTimer timer; | ||
115 | |||
116 | if (motion.Scene == null) | ||
117 | return; | ||
118 | |||
119 | lock (m_timers) | ||
120 | { | ||
121 | if (!m_timers.TryGetValue(motion.Scene, out timer)) | ||
122 | { | ||
123 | return; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | lock (timer.m_lockObject) | ||
128 | { | ||
129 | timer.m_motions.Remove(motion); | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
25 | [Serializable] | 134 | [Serializable] |
26 | public class KeyframeMotion | 135 | public class KeyframeMotion |
27 | { | 136 | { |
@@ -63,18 +172,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
63 | 172 | ||
64 | private Keyframe[] m_keyframes; | 173 | private Keyframe[] m_keyframes; |
65 | 174 | ||
66 | [NonSerialized()] | ||
67 | protected Timer m_timer = null; | ||
68 | |||
69 | // timer lock | ||
70 | [NonSerialized()] | ||
71 | private object m_onTimerLock; | ||
72 | |||
73 | // timer overrun detect | ||
74 | // prevents overlap or timer events threads frozen on the lock | ||
75 | [NonSerialized()] | ||
76 | private bool m_inOnTimer; | ||
77 | |||
78 | // skip timer events. | 175 | // skip timer events. |
79 | //timer.stop doesn't assure there aren't event threads still being fired | 176 | //timer.stop doesn't assure there aren't event threads still being fired |
80 | [NonSerialized()] | 177 | [NonSerialized()] |
@@ -97,12 +194,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
97 | private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation; | 194 | private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation; |
98 | 195 | ||
99 | private bool m_running = false; | 196 | private bool m_running = false; |
197 | |||
100 | [NonSerialized()] | 198 | [NonSerialized()] |
101 | private bool m_selected = false; | 199 | private bool m_selected = false; |
102 | 200 | ||
103 | private int m_iterations = 0; | 201 | private int m_iterations = 0; |
104 | 202 | ||
105 | private const double timerInterval = 50.0; | 203 | private int m_skipLoops = 0; |
204 | |||
205 | [NonSerialized()] | ||
206 | private Scene m_scene; | ||
207 | |||
208 | public Scene Scene | ||
209 | { | ||
210 | get { return m_scene; } | ||
211 | } | ||
106 | 212 | ||
107 | public DataFormat Data | 213 | public DataFormat Data |
108 | { | 214 | { |
@@ -139,31 +245,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
139 | 245 | ||
140 | private void StartTimer() | 246 | private void StartTimer() |
141 | { | 247 | { |
142 | if (m_timer == null) | 248 | KeyframeTimer.Add(this); |
143 | return; | ||
144 | m_timerStopped = false; | 249 | m_timerStopped = false; |
145 | m_timer.Start(); | ||
146 | } | 250 | } |
147 | 251 | ||
148 | private void StopTimer() | 252 | private void StopTimer() |
149 | { | 253 | { |
150 | if (m_timer == null || m_timerStopped) | ||
151 | return; | ||
152 | m_timerStopped = true; | ||
153 | m_timer.Stop(); | ||
154 | } | ||
155 | |||
156 | private void RemoveTimer() | ||
157 | { | ||
158 | if (m_timer == null) | ||
159 | return; | ||
160 | m_timerStopped = true; | 254 | m_timerStopped = true; |
161 | m_timer.Stop(); | 255 | KeyframeTimer.Remove(this); |
162 | m_timer.Elapsed -= OnTimer; | ||
163 | m_timer = null; | ||
164 | } | 256 | } |
165 | 257 | ||
166 | |||
167 | public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) | 258 | public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) |
168 | { | 259 | { |
169 | KeyframeMotion newMotion = null; | 260 | KeyframeMotion newMotion = null; |
@@ -177,12 +268,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
177 | 268 | ||
178 | newMotion.m_group = grp; | 269 | newMotion.m_group = grp; |
179 | 270 | ||
180 | if (grp != null && grp.IsSelected) | 271 | if (grp != null) |
181 | newMotion.m_selected = true; | 272 | { |
273 | newMotion.m_scene = grp.Scene; | ||
274 | if (grp.IsSelected) | ||
275 | newMotion.m_selected = true; | ||
276 | } | ||
182 | 277 | ||
183 | newMotion.m_onTimerLock = new object(); | ||
184 | newMotion.m_timerStopped = false; | 278 | newMotion.m_timerStopped = false; |
185 | newMotion.m_inOnTimer = false; | 279 | newMotion.m_running = true; |
186 | newMotion.m_isCrossing = false; | 280 | newMotion.m_isCrossing = false; |
187 | newMotion.m_waitingCrossing = false; | 281 | newMotion.m_waitingCrossing = false; |
188 | } | 282 | } |
@@ -196,37 +290,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
196 | 290 | ||
197 | public void UpdateSceneObject(SceneObjectGroup grp) | 291 | public void UpdateSceneObject(SceneObjectGroup grp) |
198 | { | 292 | { |
199 | // lock (m_onTimerLock) | 293 | m_isCrossing = false; |
200 | { | 294 | m_waitingCrossing = false; |
201 | m_isCrossing = false; | 295 | StopTimer(); |
202 | m_waitingCrossing = false; | ||
203 | StopTimer(); | ||
204 | 296 | ||
205 | if (grp == null) | 297 | if (grp == null) |
206 | return; | 298 | return; |
207 | 299 | ||
208 | m_group = grp; | 300 | m_group = grp; |
209 | Vector3 grppos = grp.AbsolutePosition; | 301 | m_scene = grp.Scene; |
210 | Vector3 offset = grppos - m_serializedPosition; | ||
211 | // avoid doing it more than once | ||
212 | // current this will happen draging a prim to other region | ||
213 | m_serializedPosition = grppos; | ||
214 | 302 | ||
215 | m_basePosition += offset; | 303 | Vector3 grppos = grp.AbsolutePosition; |
216 | m_currentFrame.Position += offset; | 304 | Vector3 offset = grppos - m_serializedPosition; |
305 | // avoid doing it more than once | ||
306 | // current this will happen draging a prim to other region | ||
307 | m_serializedPosition = grppos; | ||
217 | 308 | ||
218 | m_nextPosition += offset; | 309 | m_basePosition += offset; |
310 | m_currentFrame.Position += offset; | ||
219 | 311 | ||
220 | for (int i = 0; i < m_frames.Count; i++) | 312 | m_nextPosition += offset; |
221 | { | ||
222 | Keyframe k = m_frames[i]; | ||
223 | k.Position += offset; | ||
224 | m_frames[i]=k; | ||
225 | } | ||
226 | 313 | ||
227 | if (m_running) | 314 | for (int i = 0; i < m_frames.Count; i++) |
228 | Start(); | 315 | { |
316 | Keyframe k = m_frames[i]; | ||
317 | k.Position += offset; | ||
318 | m_frames[i]=k; | ||
229 | } | 319 | } |
320 | |||
321 | if (m_running) | ||
322 | Start(); | ||
230 | } | 323 | } |
231 | 324 | ||
232 | public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data) | 325 | public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data) |
@@ -239,11 +332,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
239 | { | 332 | { |
240 | m_basePosition = grp.AbsolutePosition; | 333 | m_basePosition = grp.AbsolutePosition; |
241 | m_baseRotation = grp.GroupRotation; | 334 | m_baseRotation = grp.GroupRotation; |
335 | m_scene = grp.Scene; | ||
242 | } | 336 | } |
243 | 337 | ||
244 | m_onTimerLock = new object(); | ||
245 | m_timerStopped = true; | 338 | m_timerStopped = true; |
246 | m_inOnTimer = false; | ||
247 | m_isCrossing = false; | 339 | m_isCrossing = false; |
248 | m_waitingCrossing = false; | 340 | m_waitingCrossing = false; |
249 | } | 341 | } |
@@ -260,6 +352,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
260 | KeyframeMotion newmotion = new KeyframeMotion(null, m_mode, m_data); | 352 | KeyframeMotion newmotion = new KeyframeMotion(null, m_mode, m_data); |
261 | 353 | ||
262 | newmotion.m_group = newgrp; | 354 | newmotion.m_group = newgrp; |
355 | newmotion.m_scene = newgrp.Scene; | ||
263 | 356 | ||
264 | if (m_keyframes != null) | 357 | if (m_keyframes != null) |
265 | { | 358 | { |
@@ -296,7 +389,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
296 | public void Delete() | 389 | public void Delete() |
297 | { | 390 | { |
298 | m_running = false; | 391 | m_running = false; |
299 | RemoveTimer(); | 392 | StopTimer(); |
300 | m_isCrossing = false; | 393 | m_isCrossing = false; |
301 | m_waitingCrossing = false; | 394 | m_waitingCrossing = false; |
302 | m_frames.Clear(); | 395 | m_frames.Clear(); |
@@ -309,27 +402,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
309 | m_waitingCrossing = false; | 402 | m_waitingCrossing = false; |
310 | if (m_keyframes != null && m_group != null && m_keyframes.Length > 0) | 403 | if (m_keyframes != null && m_group != null && m_keyframes.Length > 0) |
311 | { | 404 | { |
312 | if (m_timer == null) | ||
313 | { | ||
314 | m_timer = new Timer(); | ||
315 | m_timer.Interval = timerInterval; | ||
316 | m_timer.AutoReset = true; | ||
317 | m_timer.Elapsed += OnTimer; | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | StopTimer(); | ||
322 | m_timer.Interval = timerInterval; | ||
323 | } | ||
324 | |||
325 | m_inOnTimer = false; | ||
326 | StartTimer(); | 405 | StartTimer(); |
327 | m_running = true; | 406 | m_running = true; |
328 | } | 407 | } |
329 | else | 408 | else |
330 | { | 409 | { |
331 | m_running = false; | 410 | m_running = false; |
332 | RemoveTimer(); | 411 | StopTimer(); |
333 | } | 412 | } |
334 | } | 413 | } |
335 | 414 | ||
@@ -339,7 +418,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
339 | m_isCrossing = false; | 418 | m_isCrossing = false; |
340 | m_waitingCrossing = false; | 419 | m_waitingCrossing = false; |
341 | 420 | ||
342 | RemoveTimer(); | 421 | StopTimer(); |
343 | 422 | ||
344 | m_basePosition = m_group.AbsolutePosition; | 423 | m_basePosition = m_group.AbsolutePosition; |
345 | m_baseRotation = m_group.GroupRotation; | 424 | m_baseRotation = m_group.GroupRotation; |
@@ -354,7 +433,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
354 | public void Pause() | 433 | public void Pause() |
355 | { | 434 | { |
356 | m_running = false; | 435 | m_running = false; |
357 | RemoveTimer(); | 436 | StopTimer(); |
358 | 437 | ||
359 | m_group.RootPart.Velocity = Vector3.Zero; | 438 | m_group.RootPart.Velocity = Vector3.Zero; |
360 | m_group.RootPart.AngularVelocity = Vector3.Zero; | 439 | m_group.RootPart.AngularVelocity = Vector3.Zero; |
@@ -377,15 +456,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
377 | 456 | ||
378 | int start = 0; | 457 | int start = 0; |
379 | int end = m_keyframes.Length; | 458 | int end = m_keyframes.Length; |
380 | // if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1) | ||
381 | // end = m_keyframes.Length - 1; | ||
382 | 459 | ||
383 | if (direction < 0) | 460 | if (direction < 0) |
384 | { | 461 | { |
385 | start = m_keyframes.Length - 1; | 462 | start = m_keyframes.Length - 1; |
386 | end = -1; | 463 | end = -1; |
387 | // if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1) | ||
388 | // end = 0; | ||
389 | } | 464 | } |
390 | 465 | ||
391 | for (int i = start; i != end ; i += direction) | 466 | for (int i = start; i != end ; i += direction) |
@@ -463,189 +538,172 @@ namespace OpenSim.Region.Framework.Scenes | |||
463 | } | 538 | } |
464 | } | 539 | } |
465 | 540 | ||
466 | protected void OnTimer(object sender, ElapsedEventArgs e) | 541 | public void OnTimer(double tickDuration) |
467 | { | 542 | { |
468 | if (m_timerStopped) // trap events still in air even after a timer.stop | 543 | if (m_skipLoops > 0) |
469 | return; | ||
470 | |||
471 | if (m_inOnTimer) // don't let overruns to happen | ||
472 | { | 544 | { |
473 | m_log.Warn("[KeyFrame]: timer overrun"); | 545 | m_skipLoops--; |
474 | return; | 546 | return; |
475 | } | 547 | } |
476 | 548 | ||
549 | if (m_timerStopped) // trap events still in air even after a timer.stop | ||
550 | return; | ||
551 | |||
477 | if (m_group == null) | 552 | if (m_group == null) |
478 | return; | 553 | return; |
479 | 554 | ||
480 | lock (m_onTimerLock) | 555 | bool update = false; |
481 | { | ||
482 | 556 | ||
483 | m_inOnTimer = true; | 557 | if (m_selected) |
558 | { | ||
559 | if (m_group.RootPart.Velocity != Vector3.Zero) | ||
560 | { | ||
561 | m_group.RootPart.Velocity = Vector3.Zero; | ||
562 | m_group.SendGroupRootTerseUpdate(); | ||
484 | 563 | ||
485 | bool update = false; | 564 | } |
565 | return; | ||
566 | } | ||
486 | 567 | ||
487 | try | 568 | if (m_isCrossing) |
569 | { | ||
570 | // if crossing and timer running then cross failed | ||
571 | // wait some time then | ||
572 | // retry to set the position that evtually caused the outbound | ||
573 | // if still outside region this will call startCrossing below | ||
574 | m_isCrossing = false; | ||
575 | m_group.AbsolutePosition = m_nextPosition; | ||
576 | if (!m_isCrossing) | ||
488 | { | 577 | { |
489 | if (m_selected) | 578 | StopTimer(); |
490 | { | 579 | StartTimer(); |
491 | if (m_group.RootPart.Velocity != Vector3.Zero) | 580 | } |
492 | { | 581 | return; |
493 | m_group.RootPart.Velocity = Vector3.Zero; | 582 | } |
494 | m_group.SendGroupRootTerseUpdate(); | ||
495 | // m_group.RootPart.ScheduleTerseUpdate(); | ||
496 | 583 | ||
497 | } | 584 | if (m_frames.Count == 0) |
498 | m_inOnTimer = false; | 585 | { |
499 | return; | 586 | GetNextList(); |
500 | } | ||
501 | 587 | ||
502 | if (m_isCrossing) | 588 | if (m_frames.Count == 0) |
503 | { | 589 | { |
504 | // if crossing and timer running then cross failed | 590 | Stop(); |
505 | // wait some time then | 591 | Scene scene = m_group.Scene; |
506 | // retry to set the position that evtually caused the outbound | ||
507 | // if still outside region this will call startCrossing below | ||
508 | m_isCrossing = false; | ||
509 | m_group.AbsolutePosition = m_nextPosition; | ||
510 | if (!m_isCrossing) | ||
511 | { | ||
512 | StopTimer(); | ||
513 | m_timer.Interval = timerInterval; | ||
514 | StartTimer(); | ||
515 | } | ||
516 | m_inOnTimer = false; | ||
517 | return; | ||
518 | } | ||
519 | 592 | ||
520 | if (m_frames.Count == 0) | 593 | IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>(); |
594 | foreach (IScriptModule m in scriptModules) | ||
521 | { | 595 | { |
522 | GetNextList(); | 596 | if (m == null) |
597 | continue; | ||
598 | m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]); | ||
599 | } | ||
523 | 600 | ||
524 | if (m_frames.Count == 0) | 601 | return; |
525 | { | 602 | } |
526 | Stop(); | ||
527 | m_inOnTimer = false; | ||
528 | return; | ||
529 | } | ||
530 | 603 | ||
531 | m_currentFrame = m_frames[0]; | 604 | m_currentFrame = m_frames[0]; |
532 | m_currentFrame.TimeMS += (int)timerInterval; | 605 | m_currentFrame.TimeMS += (int)tickDuration; |
533 | 606 | ||
534 | //force a update on a keyframe transition | 607 | //force a update on a keyframe transition |
535 | update = true; | 608 | update = true; |
536 | } | 609 | } |
537 | 610 | ||
538 | m_currentFrame.TimeMS -= (int)timerInterval; | 611 | m_currentFrame.TimeMS -= (int)tickDuration; |
539 | 612 | ||
540 | // Do the frame processing | 613 | // Do the frame processing |
541 | double steps = (double)m_currentFrame.TimeMS / timerInterval; | 614 | double steps = (double)m_currentFrame.TimeMS / tickDuration; |
542 | 615 | ||
543 | if (steps <= 0.0) | 616 | if (steps <= 0.0) |
544 | { | 617 | { |
545 | m_group.RootPart.Velocity = Vector3.Zero; | 618 | m_group.RootPart.Velocity = Vector3.Zero; |
546 | m_group.RootPart.AngularVelocity = Vector3.Zero; | 619 | m_group.RootPart.AngularVelocity = Vector3.Zero; |
547 | 620 | ||
548 | m_nextPosition = (Vector3)m_currentFrame.Position; | 621 | m_nextPosition = (Vector3)m_currentFrame.Position; |
549 | m_group.AbsolutePosition = m_nextPosition; | 622 | m_group.AbsolutePosition = m_nextPosition; |
550 | 623 | ||
551 | // we are sending imediate updates, no doing force a extra terseUpdate | 624 | // we are sending imediate updates, no doing force a extra terseUpdate |
552 | // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); | 625 | // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); |
553 | 626 | ||
554 | m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; | 627 | m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; |
555 | m_frames.RemoveAt(0); | 628 | m_frames.RemoveAt(0); |
556 | if (m_frames.Count > 0) | 629 | if (m_frames.Count > 0) |
557 | m_currentFrame = m_frames[0]; | 630 | m_currentFrame = m_frames[0]; |
558 | 631 | ||
559 | update = true; | 632 | update = true; |
560 | } | 633 | } |
561 | else | 634 | else |
562 | { | 635 | { |
563 | float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; | 636 | float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; |
564 | 637 | ||
565 | Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition; | 638 | Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition; |
566 | Vector3 motionThisFrame = v / (float)steps; | 639 | Vector3 motionThisFrame = v / (float)steps; |
567 | v = v * 1000 / m_currentFrame.TimeMS; | 640 | v = v * 1000 / m_currentFrame.TimeMS; |
568 | 641 | ||
569 | if (Vector3.Mag(motionThisFrame) >= 0.05f) | 642 | if (Vector3.Mag(motionThisFrame) >= 0.05f) |
570 | { | 643 | { |
571 | // m_group.AbsolutePosition += motionThisFrame; | 644 | // m_group.AbsolutePosition += motionThisFrame; |
572 | m_nextPosition = m_group.AbsolutePosition + motionThisFrame; | 645 | m_nextPosition = m_group.AbsolutePosition + motionThisFrame; |
573 | m_group.AbsolutePosition = m_nextPosition; | 646 | m_group.AbsolutePosition = m_nextPosition; |
574 | 647 | ||
575 | m_group.RootPart.Velocity = v; | 648 | m_group.RootPart.Velocity = v; |
576 | update = true; | 649 | update = true; |
577 | } | 650 | } |
578 | 651 | ||
579 | if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) | 652 | if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) |
580 | { | 653 | { |
581 | Quaternion current = m_group.GroupRotation; | 654 | Quaternion current = m_group.GroupRotation; |
582 | 655 | ||
583 | Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); | 656 | Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); |
584 | step.Normalize(); | 657 | step.Normalize(); |
585 | /* use simpler change detection | 658 | /* use simpler change detection |
586 | * float angle = 0; | 659 | * float angle = 0; |
587 | |||
588 | float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; | ||
589 | float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; | ||
590 | float aa_bb = aa * bb; | ||
591 | |||
592 | if (aa_bb == 0) | ||
593 | { | ||
594 | angle = 0; | ||
595 | } | ||
596 | else | ||
597 | { | ||
598 | float ab = current.X * step.X + | ||
599 | current.Y * step.Y + | ||
600 | current.Z * step.Z + | ||
601 | current.W * step.W; | ||
602 | float q = (ab * ab) / aa_bb; | ||
603 | |||
604 | if (q > 1.0f) | ||
605 | { | ||
606 | angle = 0; | ||
607 | } | ||
608 | else | ||
609 | { | ||
610 | angle = (float)Math.Acos(2 * q - 1); | ||
611 | } | ||
612 | } | ||
613 | |||
614 | if (angle > 0.01f) | ||
615 | */ | ||
616 | if(Math.Abs(step.X - current.X) > 0.001f | ||
617 | || Math.Abs(step.Y - current.Y) > 0.001f | ||
618 | || Math.Abs(step.Z - current.Z) > 0.001f) | ||
619 | // assuming w is a dependente var | ||
620 | 660 | ||
621 | { | 661 | float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; |
622 | // m_group.UpdateGroupRotationR(step); | 662 | float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; |
623 | m_group.RootPart.RotationOffset = step; | 663 | float aa_bb = aa * bb; |
624 | 664 | ||
625 | //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); | 665 | if (aa_bb == 0) |
626 | update = true; | 666 | { |
627 | } | 667 | angle = 0; |
668 | } | ||
669 | else | ||
670 | { | ||
671 | float ab = current.X * step.X + | ||
672 | current.Y * step.Y + | ||
673 | current.Z * step.Z + | ||
674 | current.W * step.W; | ||
675 | float q = (ab * ab) / aa_bb; | ||
676 | |||
677 | if (q > 1.0f) | ||
678 | { | ||
679 | angle = 0; | ||
680 | } | ||
681 | else | ||
682 | { | ||
683 | angle = (float)Math.Acos(2 * q - 1); | ||
628 | } | 684 | } |
629 | } | 685 | } |
630 | 686 | ||
631 | if (update) | 687 | if (angle > 0.01f) |
632 | m_group.SendGroupRootTerseUpdate(); | 688 | */ |
633 | // m_group.RootPart.ScheduleTerseUpdate(); | 689 | if(Math.Abs(step.X - current.X) > 0.001f |
690 | || Math.Abs(step.Y - current.Y) > 0.001f | ||
691 | || Math.Abs(step.Z - current.Z) > 0.001f) | ||
692 | // assuming w is a dependente var | ||
634 | 693 | ||
694 | { | ||
695 | // m_group.UpdateGroupRotationR(step); | ||
696 | m_group.RootPart.RotationOffset = step; | ||
635 | 697 | ||
698 | //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); | ||
699 | update = true; | ||
700 | } | ||
636 | } | 701 | } |
637 | catch ( Exception ex) | 702 | } |
638 | { | ||
639 | // still happening sometimes | ||
640 | // lets try to see where | ||
641 | m_log.Warn("[KeyFrame]: timer overrun" + ex.Message); | ||
642 | } | ||
643 | 703 | ||
644 | finally | 704 | if (update) |
645 | { | 705 | { |
646 | // make sure we do not let this frozen | 706 | m_group.SendGroupRootTerseUpdate(); |
647 | m_inOnTimer = false; | ||
648 | } | ||
649 | } | 707 | } |
650 | } | 708 | } |
651 | 709 | ||
@@ -677,7 +735,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
677 | m_isCrossing = true; | 735 | m_isCrossing = true; |
678 | m_waitingCrossing = true; | 736 | m_waitingCrossing = true; |
679 | 737 | ||
680 | // to remove / retune to smoth crossings | 738 | // to remove / retune to smoth crossings |
681 | if (m_group.RootPart.Velocity != Vector3.Zero) | 739 | if (m_group.RootPart.Velocity != Vector3.Zero) |
682 | { | 740 | { |
683 | m_group.RootPart.Velocity = Vector3.Zero; | 741 | m_group.RootPart.Velocity = Vector3.Zero; |
@@ -696,9 +754,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
696 | m_group.SendGroupRootTerseUpdate(); | 754 | m_group.SendGroupRootTerseUpdate(); |
697 | // m_group.RootPart.ScheduleTerseUpdate(); | 755 | // m_group.RootPart.ScheduleTerseUpdate(); |
698 | 756 | ||
699 | if (m_running && m_timer != null) | 757 | if (m_running) |
700 | { | 758 | { |
701 | m_timer.Interval = 60000; | 759 | StopTimer(); |
760 | m_skipLoops = 1200; // 60 seconds | ||
702 | StartTimer(); | 761 | StartTimer(); |
703 | } | 762 | } |
704 | } | 763 | } |