aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/KeyframeMotion.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs372
1 files changed, 215 insertions, 157 deletions
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index bbf3b51..80ee510 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -140,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes
140 timer.Start(); 140 timer.Start();
141 }; 141 };
142 } 142 }
143 143
144 // Check again, in case the regions were started while we were adding the event handler 144 // Check again, in case the regions were started while we were adding the event handler
145 if (SceneManager.Instance.AllRegionsReady) 145 if (SceneManager.Instance.AllRegionsReady)
146 { 146 {
@@ -292,14 +292,18 @@ namespace OpenSim.Region.Framework.Scenes
292 292
293 private void StartTimer() 293 private void StartTimer()
294 { 294 {
295 KeyframeTimer.Add(this); 295 lock (m_frames)
296 m_timerStopped = false; 296 {
297 KeyframeTimer.Add(this);
298 m_lasttickMS = Util.GetTimeStampMS();
299 m_timerStopped = false;
300 }
297 } 301 }
298 302
299 private void StopTimer() 303 private void StopTimer()
300 { 304 {
301 m_timerStopped = true; 305 lock (m_frames)
302 KeyframeTimer.Remove(this); 306 m_timerStopped = true;
303 } 307 }
304 308
305 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) 309 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
@@ -323,8 +327,8 @@ namespace OpenSim.Region.Framework.Scenes
323 newMotion.m_selected = true; 327 newMotion.m_selected = true;
324 } 328 }
325 329
326 newMotion.m_timerStopped = false; 330// newMotion.m_timerStopped = false;
327 newMotion.m_running = true; 331// newMotion.m_running = true;
328 newMotion.m_isCrossing = false; 332 newMotion.m_isCrossing = false;
329 newMotion.m_waitingCrossing = false; 333 newMotion.m_waitingCrossing = false;
330 } 334 }
@@ -348,24 +352,26 @@ namespace OpenSim.Region.Framework.Scenes
348 m_group = grp; 352 m_group = grp;
349 m_scene = grp.Scene; 353 m_scene = grp.Scene;
350 354
351 Vector3 grppos = grp.AbsolutePosition;
352 Vector3 offset = grppos - m_serializedPosition;
353 // avoid doing it more than once
354 // current this will happen dragging a prim to other region
355 m_serializedPosition = grppos;
356 355
357 m_basePosition += offset; 356 lock (m_frames)
358 m_nextPosition += offset;
359
360 m_currentFrame.StartPosition += offset;
361 m_currentFrame.Position += offset;
362
363 for (int i = 0; i < m_frames.Count; i++)
364 { 357 {
365 Keyframe k = m_frames[i]; 358 Vector3 grppos = grp.AbsolutePosition;
366 k.StartPosition += offset; 359 Vector3 offset = grppos - m_serializedPosition;
367 k.Position += offset; 360 // avoid doing it more than once
368 m_frames[i]=k; 361 // current this will happen draging a prim to other region
362 m_serializedPosition = grppos;
363
364 m_basePosition += offset;
365 m_currentFrame.Position += offset;
366
367 m_nextPosition += offset;
368
369 for (int i = 0; i < m_frames.Count; i++)
370 {
371 Keyframe k = m_frames[i];
372 k.Position += offset;
373 m_frames[i] = k;
374 }
369 } 375 }
370 376
371 if (m_running) 377 if (m_running)
@@ -410,25 +416,28 @@ namespace OpenSim.Region.Framework.Scenes
410 m_keyframes.CopyTo(newmotion.m_keyframes, 0); 416 m_keyframes.CopyTo(newmotion.m_keyframes, 0);
411 } 417 }
412 418
413 newmotion.m_frames = new List<Keyframe>(m_frames); 419 lock (m_frames)
420 {
421 newmotion.m_frames = new List<Keyframe>(m_frames);
414 422
415 newmotion.m_basePosition = m_basePosition; 423 newmotion.m_basePosition = m_basePosition;
416 newmotion.m_baseRotation = m_baseRotation; 424 newmotion.m_baseRotation = m_baseRotation;
417 425
418 if (m_selected) 426 if (m_selected)
419 newmotion.m_serializedPosition = m_serializedPosition;
420 else
421 {
422 if (m_group != null)
423 newmotion.m_serializedPosition = m_group.AbsolutePosition;
424 else
425 newmotion.m_serializedPosition = m_serializedPosition; 427 newmotion.m_serializedPosition = m_serializedPosition;
426 } 428 else
429 {
430 if (m_group != null)
431 newmotion.m_serializedPosition = m_group.AbsolutePosition;
432 else
433 newmotion.m_serializedPosition = m_serializedPosition;
434 }
427 435
428 newmotion.m_currentFrame = m_currentFrame; 436 newmotion.m_currentFrame = m_currentFrame;
429 437
430 newmotion.m_iterations = m_iterations; 438 newmotion.m_iterations = m_iterations;
431 newmotion.m_running = m_running; 439 newmotion.m_running = m_running;
440 }
432 441
433 if (m_running && !m_waitingCrossing) 442 if (m_running && !m_waitingCrossing)
434 StartTimer(); 443 StartTimer();
@@ -458,39 +467,62 @@ namespace OpenSim.Region.Framework.Scenes
458 } 467 }
459 else 468 else
460 { 469 {
461 m_running = false;
462 StopTimer(); 470 StopTimer();
471 m_running = false;
463 } 472 }
464 } 473 }
465 474
466 public void Stop() 475 public void Stop()
467 { 476 {
477 StopTimer();
468 m_running = false; 478 m_running = false;
469 m_isCrossing = false; 479 m_isCrossing = false;
470 m_waitingCrossing = false; 480 m_waitingCrossing = false;
471 481
472 StopTimer();
473
474 m_basePosition = m_group.AbsolutePosition; 482 m_basePosition = m_group.AbsolutePosition;
475 m_baseRotation = m_group.GroupRotation; 483 m_baseRotation = m_group.GroupRotation;
476 484
477 m_group.RootPart.Velocity = Vector3.Zero; 485 m_group.RootPart.Velocity = Vector3.Zero;
478 m_group.RootPart.AngularVelocity = Vector3.Zero; 486 m_group.RootPart.AngularVelocity = Vector3.Zero;
479 m_group.SendGroupRootTerseUpdate(); 487// m_group.SendGroupRootTerseUpdate();
480// m_group.RootPart.ScheduleTerseUpdate(); 488 m_group.RootPart.ScheduleTerseUpdate();
481 m_frames.Clear(); 489 m_frames.Clear();
490 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
482 } 491 }
483 492
484 public void Pause() 493 public void Pause()
485 { 494 {
486 m_running = false;
487 StopTimer(); 495 StopTimer();
496 m_running = false;
488 497
489 m_group.RootPart.Velocity = Vector3.Zero; 498 m_group.RootPart.Velocity = Vector3.Zero;
490 m_group.RootPart.AngularVelocity = Vector3.Zero; 499 m_group.RootPart.AngularVelocity = Vector3.Zero;
491 m_group.SendGroupRootTerseUpdate(); 500 m_skippedUpdates = 1000;
492// m_group.RootPart.ScheduleTerseUpdate(); 501// m_group.SendGroupRootTerseUpdate();
502 m_group.RootPart.ScheduleTerseUpdate();
503 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
504 }
505
506 public void Suspend()
507 {
508 lock (m_frames)
509 {
510 if (m_timerStopped)
511 return;
512 m_timerStopped = true;
513 }
514 }
493 515
516 public void Resume()
517 {
518 lock (m_frames)
519 {
520 if (!m_timerStopped)
521 return;
522 if (m_running && !m_waitingCrossing)
523 StartTimer();
524 m_skippedUpdates = 1000;
525 }
494 } 526 }
495 527
496 private void GetNextList() 528 private void GetNextList()
@@ -581,6 +613,7 @@ namespace OpenSim.Region.Framework.Scenes
581 613
582 pos = (Vector3)k.Position; 614 pos = (Vector3)k.Position;
583 rot = (Quaternion)k.Rotation; 615 rot = (Quaternion)k.Rotation;
616
584 } 617 }
585 618
586 m_basePosition = pos; 619 m_basePosition = pos;
@@ -592,15 +625,47 @@ namespace OpenSim.Region.Framework.Scenes
592 625
593 public void OnTimer(double tickDuration) 626 public void OnTimer(double tickDuration)
594 { 627 {
628 if (!Monitor.TryEnter(m_frames))
629 return;
630 if (m_timerStopped)
631 KeyframeTimer.Remove(this);
632 else
633 DoOnTimer(tickDuration);
634 Monitor.Exit(m_frames);
635 }
636
637 private void Done()
638 {
639 KeyframeTimer.Remove(this);
640 m_timerStopped = true;
641 m_running = false;
642 m_isCrossing = false;
643 m_waitingCrossing = false;
644
645 m_basePosition = m_group.AbsolutePosition;
646 m_baseRotation = m_group.GroupRotation;
647
648 m_group.RootPart.Velocity = Vector3.Zero;
649 m_group.RootPart.AngularVelocity = Vector3.Zero;
650// m_group.SendGroupRootTerseUpdate();
651 m_group.RootPart.ScheduleTerseUpdate();
652 m_frames.Clear();
653 }
654
655 [NonSerialized()] Vector3 m_lastPosUpdate;
656 [NonSerialized()] Quaternion m_lastRotationUpdate;
657 [NonSerialized()] Vector3 m_currentVel;
658 [NonSerialized()] int m_skippedUpdates;
659 [NonSerialized()] double m_lasttickMS;
660
661 private void DoOnTimer(double tickDuration)
662 {
595 if (m_skipLoops > 0) 663 if (m_skipLoops > 0)
596 { 664 {
597 m_skipLoops--; 665 m_skipLoops--;
598 return; 666 return;
599 } 667 }
600 668
601 if (m_timerStopped) // trap events still in air even after a timer.stop
602 return;
603
604 if (m_group == null) 669 if (m_group == null)
605 return; 670 return;
606 671
@@ -611,8 +676,9 @@ namespace OpenSim.Region.Framework.Scenes
611 if (m_group.RootPart.Velocity != Vector3.Zero) 676 if (m_group.RootPart.Velocity != Vector3.Zero)
612 { 677 {
613 m_group.RootPart.Velocity = Vector3.Zero; 678 m_group.RootPart.Velocity = Vector3.Zero;
614 m_group.SendGroupRootTerseUpdate(); 679 m_skippedUpdates = 1000;
615 680// m_group.SendGroupRootTerseUpdate();
681 m_group.RootPart.ScheduleTerseUpdate();
616 } 682 }
617 return; 683 return;
618 } 684 }
@@ -624,7 +690,9 @@ namespace OpenSim.Region.Framework.Scenes
624 // retry to set the position that evtually caused the outbound 690 // retry to set the position that evtually caused the outbound
625 // if still outside region this will call startCrossing below 691 // if still outside region this will call startCrossing below
626 m_isCrossing = false; 692 m_isCrossing = false;
693 m_skippedUpdates = 1000;
627 m_group.AbsolutePosition = m_nextPosition; 694 m_group.AbsolutePosition = m_nextPosition;
695
628 if (!m_isCrossing) 696 if (!m_isCrossing)
629 { 697 {
630 StopTimer(); 698 StopTimer();
@@ -633,43 +701,43 @@ namespace OpenSim.Region.Framework.Scenes
633 return; 701 return;
634 } 702 }
635 703
704 double nowMS = Util.GetTimeStampMS();
705
636 if (m_frames.Count == 0) 706 if (m_frames.Count == 0)
637 { 707 {
638 if (!m_running) return; 708 lock (m_frames)
709 {
710 GetNextList();
639 711
640 GetNextList(); 712 if (m_frames.Count == 0)
713 {
714 Done();
715 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
716 return;
717 }
641 718
642 if (m_frames.Count == 0) 719 m_currentFrame = m_frames[0];
643 {
644 Stop();
645// Scene scene = m_group.Scene;
646//
647// IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
648// foreach (IScriptModule m in scriptModules)
649// {
650// if (m == null)
651// continue;
652// m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
653// }
654
655 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
656
657 return;
658 } 720 }
721 m_nextPosition = m_group.AbsolutePosition;
722 m_currentVel = (Vector3)m_currentFrame.Position - m_nextPosition;
723 m_currentVel /= (m_currentFrame.TimeMS * 0.001f);
659 724
660 m_currentFrame = m_frames[0];
661 m_currentFrame.TimeMS += (int)tickDuration; 725 m_currentFrame.TimeMS += (int)tickDuration;
662 726 m_lasttickMS = nowMS - 50f;
663 //force a update on a keyframe transition
664 update = true; 727 update = true;
665 } 728 }
666 729
667 m_currentFrame.TimeMS -= (int)tickDuration; 730 int elapsed = (int)(nowMS - m_lasttickMS);
731 if( elapsed > 3 * tickDuration)
732 elapsed = (int)tickDuration;
733
734 m_currentFrame.TimeMS -= elapsed;
735 m_lasttickMS = nowMS;
668 736
669 // Do the frame processing 737 // Do the frame processing
670 double remainingSteps = (double)m_currentFrame.TimeMS / tickDuration; 738 double remainingSteps = (double)m_currentFrame.TimeMS / tickDuration;
671 739
672 if (remainingSteps <= 0.0) 740 if (remainingSteps <= 1.0)
673 { 741 {
674 m_group.RootPart.Velocity = Vector3.Zero; 742 m_group.RootPart.Velocity = Vector3.Zero;
675 m_group.RootPart.AngularVelocity = Vector3.Zero; 743 m_group.RootPart.AngularVelocity = Vector3.Zero;
@@ -677,111 +745,99 @@ namespace OpenSim.Region.Framework.Scenes
677 m_nextPosition = (Vector3)m_currentFrame.Position; 745 m_nextPosition = (Vector3)m_currentFrame.Position;
678 m_group.AbsolutePosition = m_nextPosition; 746 m_group.AbsolutePosition = m_nextPosition;
679 747
680 // we are sending imediate updates, no doing force a extra terseUpdate
681 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
682
683 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; 748 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
684 m_frames.RemoveAt(0);
685 if (m_frames.Count > 0)
686 m_currentFrame = m_frames[0];
687 749
750 lock (m_frames)
751 {
752 m_frames.RemoveAt(0);
753 if (m_frames.Count > 0)
754 {
755 m_currentFrame = m_frames[0];
756 m_currentVel = (Vector3)m_currentFrame.Position - m_nextPosition;
757 m_currentVel /= (m_currentFrame.TimeMS * 0.001f);
758 m_group.RootPart.Velocity = m_currentVel;
759 m_currentFrame.TimeMS += (int)tickDuration;
760 }
761 else
762 m_group.RootPart.Velocity = Vector3.Zero;
763 }
688 update = true; 764 update = true;
689 } 765 }
690 else 766 else
691 { 767 {
692 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; 768// bool lastSteps = remainingSteps < 4;
693 bool lastStep = m_currentFrame.TimeMS <= tickDuration; 769
694 770 Vector3 currentPosition = m_group.AbsolutePosition;
695 Vector3 positionThisStep = m_currentFrame.StartPosition + (m_currentFrame.Position.Value - m_currentFrame.StartPosition) * completed; 771 Vector3 motionThisFrame = (Vector3)m_currentFrame.Position - currentPosition;
696 Vector3 motionThisStep = positionThisStep - m_group.AbsolutePosition; 772 motionThisFrame /= (float)remainingSteps;
697 773
698 float mag = Vector3.Mag(motionThisStep); 774 m_nextPosition = currentPosition + motionThisFrame;
699 775
700 if ((mag >= 0.02f) || lastStep) 776 Quaternion currentRotation = m_group.GroupRotation;
777 if ((Quaternion)m_currentFrame.Rotation != currentRotation)
701 { 778 {
702 m_nextPosition = m_group.AbsolutePosition + motionThisStep; 779 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
703 m_group.AbsolutePosition = m_nextPosition;
704 update = true;
705 }
706
707 //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration;
708 //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})",
709 // totalSteps - remainingSteps + 1, totalSteps, m_group.AbsolutePosition, m_currentFrame.Position, motionThisStep, m_scene.RegionInfo.RegionName);
710
711 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
712 {
713 Quaternion current = m_group.GroupRotation;
714
715 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); 780 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed);
716 step.Normalize(); 781 step.Normalize();
717/* use simpler change detection 782 m_group.RootPart.RotationOffset = step;
718* float angle = 0; 783/*
719 784 if (Math.Abs(step.X - m_lastRotationUpdate.X) > 0.001f
720 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 785 || Math.Abs(step.Y - m_lastRotationUpdate.Y) > 0.001f
721 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 786 || Math.Abs(step.Z - m_lastRotationUpdate.Z) > 0.001f)
722 float aa_bb = aa * bb;
723
724 if (aa_bb == 0)
725 {
726 angle = 0;
727 }
728 else
729 {
730 float ab = current.X * step.X +
731 current.Y * step.Y +
732 current.Z * step.Z +
733 current.W * step.W;
734 float q = (ab * ab) / aa_bb;
735
736 if (q > 1.0f)
737 {
738 angle = 0;
739 }
740 else
741 {
742 angle = (float)Math.Acos(2 * q - 1);
743 }
744 }
745
746 if (angle > 0.01f)
747*/
748 if(Math.Abs(step.X - current.X) > 0.001f
749 || Math.Abs(step.Y - current.Y) > 0.001f
750 || Math.Abs(step.Z - current.Z) > 0.001f
751 || lastStep)
752 // assuming w is a dependente var
753
754 {
755// m_group.UpdateGroupRotationR(step);
756 m_group.RootPart.RotationOffset = step;
757
758 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
759 update = true; 787 update = true;
760 } 788*/
761 } 789 }
762 }
763 790
764 if (update) 791 m_group.AbsolutePosition = m_nextPosition;
765 { 792// if(lastSteps)
766 m_group.SendGroupRootTerseUpdate(); 793// m_group.RootPart.Velocity = Vector3.Zero;
794// else
795 m_group.RootPart.Velocity = m_currentVel;
796/*
797 if(!update && (
798// lastSteps ||
799 m_skippedUpdates * tickDuration > 0.5 ||
800 Math.Abs(m_nextPosition.X - currentPosition.X) > 5f ||
801 Math.Abs(m_nextPosition.Y - currentPosition.Y) > 5f ||
802 Math.Abs(m_nextPosition.Z - currentPosition.Z) > 5f
803 ))
804 {
805 update = true;
806 }
807 else
808 m_skippedUpdates++;
809*/
767 } 810 }
811// if(update)
812// {
813// m_lastPosUpdate = m_nextPosition;
814// m_lastRotationUpdate = m_group.GroupRotation;
815// m_skippedUpdates = 0;
816// m_group.SendGroupRootTerseUpdate();
817 m_group.RootPart.ScheduleTerseUpdate();
818// }
768 } 819 }
769 820
770 public Byte[] Serialize() 821 public Byte[] Serialize()
771 { 822 {
823 bool timerWasStopped;
824 lock (m_frames)
825 {
826 timerWasStopped = m_timerStopped;
827 }
772 StopTimer(); 828 StopTimer();
773 829
774 SceneObjectGroup tmp = m_group; 830 SceneObjectGroup tmp = m_group;
775 m_group = null; 831 m_group = null;
776 if (!m_selected && tmp != null)
777 m_serializedPosition = tmp.AbsolutePosition;
778 832
779 using (MemoryStream ms = new MemoryStream()) 833 using (MemoryStream ms = new MemoryStream())
780 { 834 {
781 BinaryFormatter fmt = new BinaryFormatter(); 835 BinaryFormatter fmt = new BinaryFormatter();
836 if (!m_selected && tmp != null)
837 m_serializedPosition = tmp.AbsolutePosition;
782 fmt.Serialize(ms, this); 838 fmt.Serialize(ms, this);
783 m_group = tmp; 839 m_group = tmp;
784 if (m_running && !m_waitingCrossing) 840 if (!timerWasStopped && m_running && !m_waitingCrossing)
785 StartTimer(); 841 StartTimer();
786 842
787 return ms.ToArray(); 843 return ms.ToArray();
@@ -791,10 +847,10 @@ namespace OpenSim.Region.Framework.Scenes
791 public void StartCrossingCheck() 847 public void StartCrossingCheck()
792 { 848 {
793 // timer will be restart by crossingFailure 849 // timer will be restart by crossingFailure
794 // or never since crossing worked and this 850 // or never since crossing worked and this
795 // should be deleted 851 // should be deleted
796 StopTimer(); 852 StopTimer();
797 853
798 m_isCrossing = true; 854 m_isCrossing = true;
799 m_waitingCrossing = true; 855 m_waitingCrossing = true;
800 856
@@ -802,8 +858,9 @@ namespace OpenSim.Region.Framework.Scenes
802 if (m_group.RootPart.Velocity != Vector3.Zero) 858 if (m_group.RootPart.Velocity != Vector3.Zero)
803 { 859 {
804 m_group.RootPart.Velocity = Vector3.Zero; 860 m_group.RootPart.Velocity = Vector3.Zero;
805 m_group.SendGroupRootTerseUpdate(); 861 m_skippedUpdates = 1000;
806// m_group.RootPart.ScheduleTerseUpdate(); 862// m_group.SendGroupRootTerseUpdate();
863 m_group.RootPart.ScheduleTerseUpdate();
807 } 864 }
808 } 865 }
809 866
@@ -814,8 +871,9 @@ namespace OpenSim.Region.Framework.Scenes
814 if (m_group != null) 871 if (m_group != null)
815 { 872 {
816 m_group.RootPart.Velocity = Vector3.Zero; 873 m_group.RootPart.Velocity = Vector3.Zero;
817 m_group.SendGroupRootTerseUpdate(); 874 m_skippedUpdates = 1000;
818// m_group.RootPart.ScheduleTerseUpdate(); 875// m_group.SendGroupRootTerseUpdate();
876 m_group.RootPart.ScheduleTerseUpdate();
819 877
820 if (m_running) 878 if (m_running)
821 { 879 {