From 1324082b90a0c52a8f6d61802aff3442fb95df67 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Tue, 17 Nov 2009 15:05:40 +0000
Subject: refactor: move most animation methods from ScenePresence into a new
ScenePresenceAnimator class
---
.../Scenes/Animation/ScenePresenceAnimator.cs | 388 +++++++++++++++++++++
1 file changed, 388 insertions(+)
create mode 100644 OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
(limited to 'OpenSim/Region/Framework/Scenes/Animation')
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
new file mode 100644
index 0000000..d22e24a
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Region.Physics.Manager;
+
+namespace OpenSim.Region.Framework.Scenes.Animation
+{
+ ///
+ /// Handle all animation duties for a scene presence
+ ///
+ public class ScenePresenceAnimator
+ {
+ public AnimationSet Animations
+ {
+ get { return m_animations; }
+ }
+ protected AnimationSet m_animations = new AnimationSet();
+
+ ///
+ /// The current movement animation
+ ///
+ public string CurrentMovementAnimation
+ {
+ get { return m_movementAnimation; }
+ }
+ protected string m_movementAnimation = "DEFAULT";
+
+ private int m_animTickFall;
+ private int m_animTickJump;
+
+ ///
+ /// The scene presence that this animator applies to
+ ///
+ protected ScenePresence m_scenePresence;
+
+ public ScenePresenceAnimator(ScenePresence sp)
+ {
+ m_scenePresence = sp;
+ }
+
+ public void AddAnimation(UUID animID, UUID objectID)
+ {
+ if (m_scenePresence.IsChildAgent)
+ return;
+
+ if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
+ SendAnimPack();
+ }
+
+ // Called from scripts
+ public void AddAnimation(string name, UUID objectID)
+ {
+ if (m_scenePresence.IsChildAgent)
+ return;
+
+ UUID animID = m_scenePresence.ControllingClient.GetDefaultAnimation(name);
+ if (animID == UUID.Zero)
+ return;
+
+ AddAnimation(animID, objectID);
+ }
+
+ public void RemoveAnimation(UUID animID)
+ {
+ if (m_scenePresence.IsChildAgent)
+ return;
+
+ if (m_animations.Remove(animID))
+ SendAnimPack();
+ }
+
+ // Called from scripts
+ public void RemoveAnimation(string name)
+ {
+ if (m_scenePresence.IsChildAgent)
+ return;
+
+ UUID animID = m_scenePresence.ControllingClient.GetDefaultAnimation(name);
+ if (animID == UUID.Zero)
+ return;
+
+ RemoveAnimation(animID);
+ }
+
+ public void ResetAnimations()
+ {
+ m_animations.Clear();
+ }
+
+ ///
+ /// The movement animation is reserved for "main" animations
+ /// that are mutually exclusive, e.g. flying and sitting.
+ ///
+ public void TrySetMovementAnimation(string anim)
+ {
+ //m_log.DebugFormat("Updating movement animation to {0}", anim);
+
+ if (!m_scenePresence.IsChildAgent)
+ {
+ if (m_animations.TrySetDefaultAnimation(
+ anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero))
+ {
+ // 16384 is CHANGED_ANIMATION
+ m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 });
+ SendAnimPack();
+ }
+ }
+ }
+
+ ///
+ /// This method determines the proper movement related animation
+ ///
+ public string GetMovementAnimation()
+ {
+ const float FALL_DELAY = 0.33f;
+ const float PREJUMP_DELAY = 0.25f;
+
+ #region Inputs
+
+ AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
+ PhysicsActor actor = m_scenePresence.PhysicsActor;
+
+ // Create forward and left vectors from the current avatar rotation
+ Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation);
+ Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix);
+ Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
+
+ // Check control flags
+ bool heldForward = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
+ bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG;
+ bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS;
+ bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
+ //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
+ //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
+ bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
+ bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG;
+ //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
+ //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;
+
+ // Direction in which the avatar is trying to move
+ Vector3 move = Vector3.Zero;
+ if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
+ if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
+ if (heldLeft) { move.X += left.X; move.Y += left.Y; }
+ if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
+ if (heldUp) { move.Z += 1; }
+ if (heldDown) { move.Z -= 1; }
+
+ // Is the avatar trying to move?
+// bool moving = (move != Vector3.Zero);
+ bool jumping = m_animTickJump != 0;
+
+ #endregion Inputs
+
+ #region Flying
+
+ if (actor != null && actor.Flying)
+ {
+ m_animTickFall = 0;
+ m_animTickJump = 0;
+
+ if (move.X != 0f || move.Y != 0f)
+ {
+ return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY");
+ }
+ else if (move.Z > 0f)
+ {
+ return "HOVER_UP";
+ }
+ else if (move.Z < 0f)
+ {
+ if (actor != null && actor.IsColliding)
+ return "LAND";
+ else
+ return "HOVER_DOWN";
+ }
+ else
+ {
+ return "HOVER";
+ }
+ }
+
+ #endregion Flying
+
+ #region Falling/Floating/Landing
+
+ if (actor == null || !actor.IsColliding)
+ {
+ float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
+ float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
+
+ if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
+ {
+ // Just started falling
+ m_animTickFall = Environment.TickCount;
+ }
+ else if (!jumping && fallElapsed > FALL_DELAY)
+ {
+ // Falling long enough to trigger the animation
+ return "FALLDOWN";
+ }
+
+ return m_movementAnimation;
+ }
+
+ #endregion Falling/Floating/Landing
+
+ #region Ground Movement
+
+ if (m_movementAnimation == "FALLDOWN")
+ {
+ m_animTickFall = Environment.TickCount;
+
+ // TODO: SOFT_LAND support
+ return "LAND";
+ }
+ else if (m_movementAnimation == "LAND")
+ {
+ float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
+
+ if (landElapsed <= FALL_DELAY)
+ return "LAND";
+ }
+
+ m_animTickFall = 0;
+
+ if (move.Z > 0f)
+ {
+ // Jumping
+ if (!jumping)
+ {
+ // Begin prejump
+ m_animTickJump = Environment.TickCount;
+ return "PREJUMP";
+ }
+ else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f)
+ {
+ // Start actual jump
+ if (m_animTickJump == -1)
+ {
+ // Already jumping! End the current jump
+ m_animTickJump = 0;
+ return "JUMP";
+ }
+
+ m_animTickJump = -1;
+ return "JUMP";
+ }
+ }
+ else
+ {
+ // Not jumping
+ m_animTickJump = 0;
+
+ if (move.X != 0f || move.Y != 0f)
+ {
+ // Walking / crouchwalking / running
+ if (move.Z < 0f)
+ return "CROUCHWALK";
+ else if (m_scenePresence.SetAlwaysRun)
+ return "RUN";
+ else
+ return "WALK";
+ }
+ else
+ {
+ // Not walking
+ if (move.Z < 0f)
+ return "CROUCH";
+ else
+ return "STAND";
+ }
+ }
+
+ #endregion Ground Movement
+
+ return m_movementAnimation;
+ }
+
+ ///
+ /// Update the movement animation of this avatar according to its current state
+ ///
+ public void UpdateMovementAnimations()
+ {
+ m_movementAnimation = GetMovementAnimation();
+
+ if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
+ {
+ // This was the previous behavior before PREJUMP
+ TrySetMovementAnimation("JUMP");
+ }
+ else
+ {
+ TrySetMovementAnimation(m_movementAnimation);
+ }
+ }
+
+ public UUID[] GetAnimationArray()
+ {
+ UUID[] animIDs;
+ int[] sequenceNums;
+ UUID[] objectIDs;
+ m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
+ return animIDs;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
+ {
+ if (m_scenePresence.IsChildAgent)
+ return;
+
+ m_scenePresence.Scene.ForEachClient(
+ delegate(IClientAPI client)
+ {
+ client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
+ });
+ }
+
+ public void SendAnimPackToClient(IClientAPI client)
+ {
+ if (m_scenePresence.IsChildAgent)
+ return;
+
+ UUID[] animIDs;
+ int[] sequenceNums;
+ UUID[] objectIDs;
+
+ m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
+
+ m_scenePresence.ControllingClient.SendAnimations(
+ animIDs, sequenceNums, m_scenePresence.ControllingClient.AgentId, objectIDs);
+ }
+
+ ///
+ /// Send animation information about this avatar to all clients.
+ ///
+ public void SendAnimPack()
+ {
+ //m_log.Debug("Sending animation pack to all");
+
+ if (m_scenePresence.IsChildAgent)
+ return;
+
+ UUID[] animIDs;
+ int[] sequenceNums;
+ UUID[] objectIDs;
+
+ m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
+
+ SendAnimPack(animIDs, sequenceNums, objectIDs);
+ }
+ }
+}
\ No newline at end of file
--
cgit v1.1
From 61c76d1810fcb430cf9c7441044c70486efd9bc5 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Tue, 17 Nov 2009 15:20:02 +0000
Subject: refactor: move AnimationSet
---
.../Framework/Scenes/Animation/AnimationSet.cs | 185 +++++++++++++++++++++
1 file changed, 185 insertions(+)
create mode 100644 OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
(limited to 'OpenSim/Region/Framework/Scenes/Animation')
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
new file mode 100644
index 0000000..9176d3d
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using OpenSim.Framework;
+using OpenMetaverse;
+
+using Animation = OpenSim.Framework.Animation;
+
+namespace OpenSim.Region.Framework.Scenes.Animation
+{
+ [Serializable]
+ public class AnimationSet
+ {
+ public static AvatarAnimations Animations = new AvatarAnimations();
+
+ private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation();
+ private List m_animations = new List();
+
+ public OpenSim.Framework.Animation DefaultAnimation
+ {
+ get { return m_defaultAnimation; }
+ }
+
+ public AnimationSet()
+ {
+ ResetDefaultAnimation();
+ }
+
+ public bool HasAnimation(UUID animID)
+ {
+ if (m_defaultAnimation.AnimID == animID)
+ return true;
+
+ for (int i = 0; i < m_animations.Count; ++i)
+ {
+ if (m_animations[i].AnimID == animID)
+ return true;
+ }
+
+ return false;
+ }
+
+ public bool Add(UUID animID, int sequenceNum, UUID objectID)
+ {
+ lock (m_animations)
+ {
+ if (!HasAnimation(animID))
+ {
+ m_animations.Add(new OpenSim.Framework.Animation(animID, sequenceNum, objectID));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool Remove(UUID animID)
+ {
+ lock (m_animations)
+ {
+ if (m_defaultAnimation.AnimID == animID)
+ {
+ ResetDefaultAnimation();
+ }
+ else if (HasAnimation(animID))
+ {
+ for (int i = 0; i < m_animations.Count; i++)
+ {
+ if (m_animations[i].AnimID == animID)
+ {
+ m_animations.RemoveAt(i);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public void Clear()
+ {
+ ResetDefaultAnimation();
+ m_animations.Clear();
+ }
+
+ ///
+ /// The default animation is reserved for "main" animations
+ /// that are mutually exclusive, e.g. flying and sitting.
+ ///
+ public bool SetDefaultAnimation(UUID animID, int sequenceNum, UUID objectID)
+ {
+ if (m_defaultAnimation.AnimID != animID)
+ {
+ m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID);
+ return true;
+ }
+ return false;
+ }
+
+ protected bool ResetDefaultAnimation()
+ {
+ return TrySetDefaultAnimation("STAND", 1, UUID.Zero);
+ }
+
+ ///
+ /// Set the animation as the default animation if it's known
+ ///
+ public bool TrySetDefaultAnimation(string anim, int sequenceNum, UUID objectID)
+ {
+ if (Animations.AnimsUUID.ContainsKey(anim))
+ {
+ return SetDefaultAnimation(Animations.AnimsUUID[anim], sequenceNum, objectID);
+ }
+ return false;
+ }
+
+ public void GetArrays(out UUID[] animIDs, out int[] sequenceNums, out UUID[] objectIDs)
+ {
+ lock (m_animations)
+ {
+ animIDs = new UUID[m_animations.Count + 1];
+ sequenceNums = new int[m_animations.Count + 1];
+ objectIDs = new UUID[m_animations.Count + 1];
+
+ animIDs[0] = m_defaultAnimation.AnimID;
+ sequenceNums[0] = m_defaultAnimation.SequenceNum;
+ objectIDs[0] = m_defaultAnimation.ObjectID;
+
+ for (int i = 0; i < m_animations.Count; ++i)
+ {
+ animIDs[i + 1] = m_animations[i].AnimID;
+ sequenceNums[i + 1] = m_animations[i].SequenceNum;
+ objectIDs[i + 1] = m_animations[i].ObjectID;
+ }
+ }
+ }
+
+ public OpenSim.Framework.Animation[] ToArray()
+ {
+ OpenSim.Framework.Animation[] theArray = new OpenSim.Framework.Animation[m_animations.Count];
+ uint i = 0;
+ try
+ {
+ foreach (OpenSim.Framework.Animation anim in m_animations)
+ theArray[i++] = anim;
+ }
+ catch
+ {
+ /* S%^t happens. Ignore. */
+ }
+ return theArray;
+ }
+
+ public void FromArray(OpenSim.Framework.Animation[] theArray)
+ {
+ foreach (OpenSim.Framework.Animation anim in theArray)
+ m_animations.Add(anim);
+ }
+ }
+}
--
cgit v1.1
From da255be05a451ba9a48efd6f167849228a54273b Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Tue, 17 Nov 2009 16:25:52 +0000
Subject: refactor: move AvatarAnimations, BinBVHAnimation
---
.../Framework/Scenes/Animation/AvatarAnimations.cs | 63 ++
.../Framework/Scenes/Animation/BinBVHAnimation.cs | 643 +++++++++++++++++++++
.../Scenes/Animation/ScenePresenceAnimator.cs | 60 ++
3 files changed, 766 insertions(+)
create mode 100644 OpenSim/Region/Framework/Scenes/Animation/AvatarAnimations.cs
create mode 100644 OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs
(limited to 'OpenSim/Region/Framework/Scenes/Animation')
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AvatarAnimations.cs b/OpenSim/Region/Framework/Scenes/Animation/AvatarAnimations.cs
new file mode 100644
index 0000000..659c3a5
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/AvatarAnimations.cs
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System.Collections.Generic;
+using System.Xml;
+using OpenMetaverse;
+
+namespace OpenSim.Region.Framework.Scenes.Animation
+{
+ public class AvatarAnimations
+ {
+ public Dictionary AnimsUUID = new Dictionary();
+ public Dictionary AnimsNames = new Dictionary();
+ public Dictionary AnimStateNames = new Dictionary();
+
+ public AvatarAnimations()
+ {
+ using (XmlTextReader reader = new XmlTextReader("data/avataranimations.xml"))
+ {
+ XmlDocument doc = new XmlDocument();
+ doc.Load(reader);
+ foreach (XmlNode nod in doc.DocumentElement.ChildNodes)
+ {
+ if (nod.Attributes["name"] != null)
+ {
+ string name = (string)nod.Attributes["name"].Value;
+ UUID id = (UUID)nod.InnerText;
+ string animState = (string)nod.Attributes["state"].Value;
+
+ AnimsUUID.Add(name, id);
+ AnimsNames.Add(id, name);
+ if (animState != "")
+ AnimStateNames.Add(id, animState);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs b/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs
new file mode 100644
index 0000000..3afc87f
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs
@@ -0,0 +1,643 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.IO;
+using OpenMetaverse;
+
+namespace OpenSim.Region.Framework.Scenes.Animation
+{
+ ///
+ /// Written to decode and encode a binary animation asset.
+ /// The SecondLife Client reads in a BVH file and converts
+ /// it to the format described here. This isn't
+ ///
+ public class BinBVHAnimation
+ {
+ ///
+ /// Rotation Keyframe count (used internally)
+ /// Don't use this, use the rotationkeys.Length on each joint
+ ///
+ private int rotationkeys;
+
+ ///
+ /// Position Keyframe count (used internally)
+ /// Don't use this, use the positionkeys.Length on each joint
+ ///
+ private int positionkeys;
+
+ public UInt16 unknown0; // Always 1
+ public UInt16 unknown1; // Always 0
+
+ ///
+ /// Animation Priority
+ ///
+ public int Priority;
+
+ ///
+ /// The animation length in seconds.
+ ///
+ public Single Length;
+
+ ///
+ /// Expression set in the client. Null if [None] is selected
+ ///
+ public string ExpressionName; // "" (null)
+
+ ///
+ /// The time in seconds to start the animation
+ ///
+ public Single InPoint;
+
+ ///
+ /// The time in seconds to end the animation
+ ///
+ public Single OutPoint;
+
+ ///
+ /// Loop the animation
+ ///
+ public bool Loop;
+
+ ///
+ /// Meta data. Ease in Seconds.
+ ///
+ public Single EaseInTime;
+
+ ///
+ /// Meta data. Ease out seconds.
+ ///
+ public Single EaseOutTime;
+
+ ///
+ /// Meta Data for the Hand Pose
+ ///
+ public uint HandPose;
+
+ ///
+ /// Number of joints defined in the animation
+ /// Don't use this.. use joints.Length
+ ///
+ private uint m_jointCount;
+
+
+ ///
+ /// Contains an array of joints
+ ///
+ public binBVHJoint[] Joints;
+
+
+ public byte[] ToBytes()
+ {
+ byte[] outputbytes = new byte[0];
+
+ BinaryWriter iostream = new BinaryWriter(new MemoryStream());
+ iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(unknown0)));
+ iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(unknown1)));
+ iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Priority)));
+ iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(Length)));
+ iostream.Write(BinBVHUtil.WriteNullTerminatedString(ExpressionName));
+ iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(InPoint)));
+ iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(OutPoint)));
+ iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Loop ? 1 : 0)));
+ iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(EaseInTime)));
+ iostream.Write(BinBVHUtil.ES(Utils.FloatToBytes(EaseOutTime)));
+ iostream.Write(BinBVHUtil.ES(Utils.UIntToBytes(HandPose)));
+ iostream.Write(BinBVHUtil.ES(Utils.UIntToBytes((uint)(Joints.Length))));
+
+ for (int i = 0; i < Joints.Length; i++)
+ {
+ Joints[i].WriteBytesToStream(iostream, InPoint, OutPoint);
+ }
+ iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(0)));
+ MemoryStream ms = (MemoryStream)iostream.BaseStream;
+ outputbytes = ms.ToArray();
+ ms.Close();
+ iostream.Close();
+ return outputbytes;
+ }
+
+ public BinBVHAnimation()
+ {
+ rotationkeys = 0;
+ positionkeys = 0;
+ unknown0 = 1;
+ unknown1 = 0;
+ Priority = 1;
+ Length = 0;
+ ExpressionName = string.Empty;
+ InPoint = 0;
+ OutPoint = 0;
+ Loop = false;
+ EaseInTime = 0;
+ EaseOutTime = 0;
+ HandPose = 1;
+ m_jointCount = 0;
+
+ Joints = new binBVHJoint[1];
+ Joints[0] = new binBVHJoint();
+ Joints[0].Name = "mPelvis";
+ Joints[0].Priority = 7;
+ Joints[0].positionkeys = new binBVHJointKey[1];
+ Joints[0].rotationkeys = new binBVHJointKey[1];
+ Random rnd = new Random();
+
+ Joints[0].rotationkeys[0] = new binBVHJointKey();
+ Joints[0].rotationkeys[0].time = (0f);
+ Joints[0].rotationkeys[0].key_element.X = ((float)rnd.NextDouble() * 2 - 1);
+ Joints[0].rotationkeys[0].key_element.Y = ((float)rnd.NextDouble() * 2 - 1);
+ Joints[0].rotationkeys[0].key_element.Z = ((float)rnd.NextDouble() * 2 - 1);
+
+ Joints[0].positionkeys[0] = new binBVHJointKey();
+ Joints[0].positionkeys[0].time = (0f);
+ Joints[0].positionkeys[0].key_element.X = ((float)rnd.NextDouble() * 2 - 1);
+ Joints[0].positionkeys[0].key_element.Y = ((float)rnd.NextDouble() * 2 - 1);
+ Joints[0].positionkeys[0].key_element.Z = ((float)rnd.NextDouble() * 2 - 1);
+
+
+ }
+
+ public BinBVHAnimation(byte[] animationdata)
+ {
+ int i = 0;
+ if (!BitConverter.IsLittleEndian)
+ {
+ unknown0 = Utils.BytesToUInt16(BinBVHUtil.EndianSwap(animationdata,i,2)); i += 2; // Always 1
+ unknown1 = Utils.BytesToUInt16(BinBVHUtil.EndianSwap(animationdata, i, 2)); i += 2; // Always 0
+ Priority = Utils.BytesToInt(BinBVHUtil.EndianSwap(animationdata, i, 4)); i += 4;
+ Length = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
+ }
+ else
+ {
+ unknown0 = Utils.BytesToUInt16(animationdata, i); i += 2; // Always 1
+ unknown1 = Utils.BytesToUInt16(animationdata, i); i += 2; // Always 0
+ Priority = Utils.BytesToInt(animationdata, i); i += 4;
+ Length = Utils.BytesToFloat(animationdata, i); i += 4;
+ }
+ ExpressionName = ReadBytesUntilNull(animationdata, ref i);
+ if (!BitConverter.IsLittleEndian)
+ {
+ InPoint = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
+ OutPoint = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
+ Loop = (Utils.BytesToInt(BinBVHUtil.EndianSwap(animationdata, i, 4)) != 0); i += 4;
+ EaseInTime = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
+ EaseOutTime = Utils.BytesToFloat(BinBVHUtil.EndianSwap(animationdata, i, 4), 0); i += 4;
+ HandPose = Utils.BytesToUInt(BinBVHUtil.EndianSwap(animationdata, i, 4)); i += 4; // Handpose?
+
+ m_jointCount = Utils.BytesToUInt(animationdata, i); i += 4; // Get Joint count
+ }
+ else
+ {
+ InPoint = Utils.BytesToFloat(animationdata, i); i += 4;
+ OutPoint = Utils.BytesToFloat(animationdata, i); i += 4;
+ Loop = (Utils.BytesToInt(animationdata, i) != 0); i += 4;
+ EaseInTime = Utils.BytesToFloat(animationdata, i); i += 4;
+ EaseOutTime = Utils.BytesToFloat(animationdata, i); i += 4;
+ HandPose = Utils.BytesToUInt(animationdata, i); i += 4; // Handpose?
+
+ m_jointCount = Utils.BytesToUInt(animationdata, i); i += 4; // Get Joint count
+ }
+ Joints = new binBVHJoint[m_jointCount];
+
+ // deserialize the number of joints in the animation.
+ // Joints are variable length blocks of binary data consisting of joint data and keyframes
+ for (int iter = 0; iter < m_jointCount; iter++)
+ {
+ binBVHJoint joint = readJoint(animationdata, ref i);
+ Joints[iter] = joint;
+ }
+ }
+
+
+ ///
+ /// Variable length strings seem to be null terminated in the animation asset.. but..
+ /// use with caution, home grown.
+ /// advances the index.
+ ///
+ /// The animation asset byte array
+ /// The offset to start reading
+ /// a string
+ private static string ReadBytesUntilNull(byte[] data, ref int i)
+ {
+ char nterm = '\0'; // Null terminator
+ int endpos = i;
+ int startpos = i;
+
+ // Find the null character
+ for (int j = i; j < data.Length; j++)
+ {
+ char spot = Convert.ToChar(data[j]);
+ if (spot == nterm)
+ {
+ endpos = j;
+ break;
+ }
+ }
+
+ // if we got to the end, then it's a zero length string
+ if (i == endpos)
+ {
+ // advance the 1 null character
+ i++;
+ return string.Empty;
+ }
+ else
+ {
+ // We found the end of the string
+ // append the bytes from the beginning of the string to the end of the string
+ // advance i
+ byte[] interm = new byte[endpos-i];
+ for (; i
+ /// Read in a Joint from an animation asset byte array
+ /// Variable length Joint fields, yay!
+ /// Advances the index
+ ///
+ /// animation asset byte array
+ /// Byte Offset of the start of the joint
+ /// The Joint data serialized into the binBVHJoint structure
+ private binBVHJoint readJoint(byte[] data, ref int i)
+ {
+
+ binBVHJointKey[] positions;
+ binBVHJointKey[] rotations;
+
+ binBVHJoint pJoint = new binBVHJoint();
+
+ /*
+ 109
+ 84
+ 111
+ 114
+ 114
+ 111
+ 0 <--- Null terminator
+ */
+
+ pJoint.Name = ReadBytesUntilNull(data, ref i); // Joint name
+
+ /*
+ 2 <- Priority Revisited
+ 0
+ 0
+ 0
+ */
+
+ /*
+ 5 <-- 5 keyframes
+ 0
+ 0
+ 0
+ ... 5 Keyframe data blocks
+ */
+
+ /*
+ 2 <-- 2 keyframes
+ 0
+ 0
+ 0
+ .. 2 Keyframe data blocks
+ */
+ if (!BitConverter.IsLittleEndian)
+ {
+ pJoint.Priority = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // Joint Priority override?
+ rotationkeys = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // How many rotation keyframes
+ }
+ else
+ {
+ pJoint.Priority = Utils.BytesToInt(data, i); i += 4; // Joint Priority override?
+ rotationkeys = Utils.BytesToInt(data, i); i += 4; // How many rotation keyframes
+ }
+
+ // argh! floats into two bytes!.. bad bad bad bad
+ // After fighting with it for a while.. -1, to 1 seems to give the best results
+ rotations = readKeys(data, ref i, rotationkeys, -1f, 1f);
+ for (int iter = 0; iter < rotations.Length; iter++)
+ {
+ rotations[iter].W = 1f -
+ (rotations[iter].key_element.X + rotations[iter].key_element.Y +
+ rotations[iter].key_element.Z);
+ }
+
+
+ if (!BitConverter.IsLittleEndian)
+ {
+ positionkeys = Utils.BytesToInt(BinBVHUtil.EndianSwap(data, i, 4)); i += 4; // How many position keyframes
+ }
+ else
+ {
+ positionkeys = Utils.BytesToInt(data, i); i += 4; // How many position keyframes
+ }
+
+ // Read in position keyframes
+ // argh! more floats into two bytes!.. *head desk*
+ // After fighting with it for a while.. -5, to 5 seems to give the best results
+ positions = readKeys(data, ref i, positionkeys, -5f, 5f);
+
+ pJoint.rotationkeys = rotations;
+ pJoint.positionkeys = positions;
+
+ return pJoint;
+ }
+
+ ///
+ /// Read Keyframes of a certain type
+ /// advance i
+ ///
+ /// Animation Byte array
+ /// Offset in the Byte Array. Will be advanced
+ /// Number of Keyframes
+ /// Scaling Min to pass to the Uint16ToFloat method
+ /// Scaling Max to pass to the Uint16ToFloat method
+ ///
+ private binBVHJointKey[] readKeys(byte[] data, ref int i, int keycount, float min, float max)
+ {
+ float x;
+ float y;
+ float z;
+
+ /*
+ 0.o, Float values in Two bytes.. this is just wrong >:(
+ 17 255 <-- Time Code
+ 17 255 <-- Time Code
+ 255 255 <-- X
+ 127 127 <-- X
+ 255 255 <-- Y
+ 127 127 <-- Y
+ 213 213 <-- Z
+ 142 142 <---Z
+
+ */
+
+ binBVHJointKey[] m_keys = new binBVHJointKey[keycount];
+ for (int j = 0; j < keycount; j++)
+ {
+ binBVHJointKey pJKey = new binBVHJointKey();
+ if (!BitConverter.IsLittleEndian)
+ {
+ pJKey.time = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, InPoint, OutPoint); i += 2;
+ x = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2;
+ y = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2;
+ z = Utils.UInt16ToFloat(BinBVHUtil.EndianSwap(data, i, 2), 0, min, max); i += 2;
+ }
+ else
+ {
+ pJKey.time = Utils.UInt16ToFloat(data, i, InPoint, OutPoint); i += 2;
+ x = Utils.UInt16ToFloat(data, i, min, max); i += 2;
+ y = Utils.UInt16ToFloat(data, i, min, max); i += 2;
+ z = Utils.UInt16ToFloat(data, i, min, max); i += 2;
+ }
+ pJKey.key_element = new Vector3(x, y, z);
+ m_keys[j] = pJKey;
+ }
+ return m_keys;
+ }
+
+
+
+ }
+ ///
+ /// A Joint and it's associated meta data and keyframes
+ ///
+ public struct binBVHJoint
+ {
+ ///
+ /// Name of the Joint. Matches the avatar_skeleton.xml in client distros
+ ///
+ public string Name;
+
+ ///
+ /// Joint Animation Override? Was the same as the Priority in testing..
+ ///
+ public int Priority;
+
+ ///
+ /// Array of Rotation Keyframes in order from earliest to latest
+ ///
+ public binBVHJointKey[] rotationkeys;
+
+ ///
+ /// Array of Position Keyframes in order from earliest to latest
+ /// This seems to only be for the Pelvis?
+ ///
+ public binBVHJointKey[] positionkeys;
+
+
+
+ public void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint)
+ {
+ iostream.Write(BinBVHUtil.WriteNullTerminatedString(Name));
+ iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(Priority)));
+ iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(rotationkeys.Length)));
+ for (int i=0;i
+ /// A Joint Keyframe. This is either a position or a rotation.
+ ///
+ public struct binBVHJointKey
+ {
+ // Time in seconds for this keyframe.
+ public float time;
+
+ ///
+ /// Either a Vector3 position or a Vector3 Euler rotation
+ ///
+ public Vector3 key_element;
+
+ public float W;
+
+ public void WriteBytesToStream(BinaryWriter iostream, float InPoint, float OutPoint, float min, float max)
+ {
+ iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(time, InPoint, OutPoint))));
+ iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.X, min, max))));
+ iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.Y, min, max))));
+ iostream.Write(BinBVHUtil.ES(Utils.UInt16ToBytes(BinBVHUtil.FloatToUInt16(key_element.Z, min, max))));
+ }
+ }
+
+ ///
+ /// Poses set in the animation metadata for the hands.
+ ///
+ public enum HandPose : uint
+ {
+ Spread = 0,
+ Relaxed = 1,
+ Point_Both = 2,
+ Fist = 3,
+ Relaxed_Left = 4,
+ Point_Left = 5,
+ Fist_Left = 6,
+ Relaxed_Right = 7,
+ Point_Right = 8,
+ Fist_Right = 9,
+ Salute_Right = 10,
+ Typing = 11,
+ Peace_Right = 12
+ }
+ public static class BinBVHUtil
+ {
+ public const float ONE_OVER_U16_MAX = 1.0f / UInt16.MaxValue;
+
+ public static UInt16 FloatToUInt16(float val, float lower, float upper)
+ {
+ UInt16 uival = 0;
+ //m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue
+ //0-1
+
+// float difference = upper - lower;
+ // we're trying to get a zero lower and modify all values equally so we get a percentage position
+ if (lower > 0)
+ {
+ upper -= lower;
+ val = val - lower;
+
+ // start with 500 upper and 200 lower.. subtract 200 from the upper and the value
+ }
+ else //if (lower < 0 && upper > 0)
+ {
+ // double negative, 0 minus negative 5 is 5.
+ upper += 0 - lower;
+ lower += 0 - lower;
+ val += 0 - lower;
+ }
+
+ if (upper == 0)
+ val = 0;
+ else
+ {
+ val /= upper;
+ }
+
+ uival = (UInt16)(val * UInt16.MaxValue);
+
+ return uival;
+ }
+
+
+ ///
+ /// Endian Swap
+ /// Swaps endianness if necessary
+ ///
+ /// Input array
+ ///
+ public static byte[] ES(byte[] arr)
+ {
+ if (!BitConverter.IsLittleEndian)
+ Array.Reverse(arr);
+ return arr;
+ }
+ public static byte[] EndianSwap(byte[] arr, int offset, int len)
+ {
+ byte[] bendian = new byte[offset + len];
+ Buffer.BlockCopy(arr, offset, bendian, 0, len);
+ Array.Reverse(bendian);
+ return bendian;
+ }
+
+ public static byte[] WriteNullTerminatedString(string str)
+ {
+ byte[] output = new byte[str.Length + 1];
+ Char[] chr = str.ToCharArray();
+ int i = 0;
+ for (i = 0; i < chr.Length; i++)
+ {
+ output[i] = Convert.ToByte(chr[i]);
+
+ }
+
+ output[i] = Convert.ToByte('\0');
+ return output;
+ }
+
+ }
+}
+/*
+switch (jointname)
+ {
+ case "mPelvis":
+ case "mTorso":
+ case "mNeck":
+ case "mHead":
+ case "mChest":
+ case "mHipLeft":
+ case "mHipRight":
+ case "mKneeLeft":
+ case "mKneeRight":
+ // XYZ->ZXY
+ t = x;
+ x = y;
+ y = t;
+ break;
+ case "mCollarLeft":
+ case "mCollarRight":
+ case "mElbowLeft":
+ case "mElbowRight":
+ // YZX ->ZXY
+ t = z;
+ z = x;
+ x = y;
+ y = t;
+ break;
+ case "mWristLeft":
+ case "mWristRight":
+ case "mShoulderLeft":
+ case "mShoulderRight":
+ // ZYX->ZXY
+ t = y;
+ y = z;
+ z = t;
+
+ break;
+ case "mAnkleLeft":
+ case "mAnkleRight":
+ // XYZ ->ZXY
+ t = x;
+ x = z;
+ z = y;
+ y = t;
+ break;
+ }
+*/
\ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index d22e24a..cbe4118 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -26,6 +26,7 @@
*/
using System;
+using System.Collections.Generic;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
@@ -331,6 +332,65 @@ namespace OpenSim.Region.Framework.Scenes.Animation
UUID[] objectIDs;
m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
return animIDs;
+ }
+
+ public BinBVHAnimation GenerateRandomAnimation()
+ {
+ int rnditerations = 3;
+ BinBVHAnimation anim = new BinBVHAnimation();
+ List parts = new List();
+ parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso");
+ parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft");
+ parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck");
+ parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight");
+ parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight");
+ parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight");
+ parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft");
+ anim.HandPose = 1;
+ anim.InPoint = 0;
+ anim.OutPoint = (rnditerations * .10f);
+ anim.Priority = 7;
+ anim.Loop = false;
+ anim.Length = (rnditerations * .10f);
+ anim.ExpressionName = "afraid";
+ anim.EaseInTime = 0;
+ anim.EaseOutTime = 0;
+
+ string[] strjoints = parts.ToArray();
+ anim.Joints = new binBVHJoint[strjoints.Length];
+ for (int j = 0; j < strjoints.Length; j++)
+ {
+ anim.Joints[j] = new binBVHJoint();
+ anim.Joints[j].Name = strjoints[j];
+ anim.Joints[j].Priority = 7;
+ anim.Joints[j].positionkeys = new binBVHJointKey[rnditerations];
+ anim.Joints[j].rotationkeys = new binBVHJointKey[rnditerations];
+ Random rnd = new Random();
+ for (int i = 0; i < rnditerations; i++)
+ {
+ anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
+ anim.Joints[j].rotationkeys[i].time = (i*.10f);
+ anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1);
+ anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1);
+ anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1);
+ anim.Joints[j].positionkeys[i] = new binBVHJointKey();
+ anim.Joints[j].positionkeys[i].time = (i*.10f);
+ anim.Joints[j].positionkeys[i].key_element.X = 0;
+ anim.Joints[j].positionkeys[i].key_element.Y = 0;
+ anim.Joints[j].positionkeys[i].key_element.Z = 0;
+ }
+ }
+
+ AssetBase Animasset = new AssetBase(UUID.Random(), "Random Animation", (sbyte)AssetType.Animation);
+ Animasset.Data = anim.ToBytes();
+ Animasset.Temporary = true;
+ Animasset.Local = true;
+ Animasset.Description = "dance";
+ //BinBVHAnimation bbvhanim = new BinBVHAnimation(Animasset.Data);
+
+ m_scenePresence.Scene.AssetService.Store(Animasset);
+ AddAnimation(Animasset.FullID, m_scenePresence.UUID);
+ return anim;
}
///
--
cgit v1.1